Symbols.cpp revision 36da2aa6dc5ad9994b638ed09eb81c44cc05540b
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
128cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            // Emit some warning messages since the UUIDs do not match!
129cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            char path_buf[PATH_MAX];
130cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            path_buf[0] = '\0';
131cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf
132cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen                                                                     : file_spec.GetFilename().AsCString();
1339262cd52e254fb261334254a80a1b316d59b555cJohnny Chen            StreamString ss_m_uuid, ss_o_uuid;
1349262cd52e254fb261334254a80a1b316d59b555cJohnny Chen            uuid->Dump(&ss_m_uuid);
1359262cd52e254fb261334254a80a1b316d59b555cJohnny Chen            file_uuid.Dump(&ss_o_uuid);
136cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            Host::SystemLog (Host::eSystemLogWarning,
1379262cd52e254fb261334254a80a1b316d59b555cJohnny Chen                             "warning: UUID mismatch detected between binary (%s) and:\n\t'%s' (%s)\n",
1389262cd52e254fb261334254a80a1b316d59b555cJohnny Chen                             ss_m_uuid.GetData(), path, ss_o_uuid.GetData());
139cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            return false;
14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset = cmd_offset + cmd_size;
14224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerUniversalMachOFileContainsArchAndUUID
14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
1510467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid,
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset,
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor& data,
15436da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    lldb::offset_t data_offset,
15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t magic
15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
1581674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    assert(magic == UniversalMagic || magic == UniversalMagicSwapped);
15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Universal mach-o files always have their headers encoded as BIG endian
16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    data.SetByteOrder(eByteOrderBig);
16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
16324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t i;
16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t nfat_arch = data.GetU32(&data_offset);   // number of structs that follow
16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch);
16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data.GetByteSize() < fat_header_and_arch_size)
16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size));
16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetData (data_buffer_sp);
17024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    for (i=0; i<nfat_arch; i++)
17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        cpu_type_t      arch_cputype        = data.GetU32(&data_offset);    // cpu specifier (int)
17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        cpu_subtype_t   arch_cpusubtype     = data.GetU32(&data_offset);    // machine specifier (int)
17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t        arch_offset         = data.GetU32(&data_offset);    // file offset to this object file
17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  uint32_t        arch_size           = data.GetU32(&data_offset);    // size of this object file
17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  uint32_t        arch_align          = data.GetU32(&data_offset);    // alignment as a power of 2
17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset += 8;   // Skip size and align as we don't need those
18024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Only process this slice if the cpu type/subtype matches
18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (arch)
18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
183cf0150574a0a97049efe2dce2cc0aa433705feb3Greg Clayton            ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype);
18464246cda58b64208f5c415fc52909c45c3dc3e2bSean Callanan            if (!fat_arch.IsExactMatch(*arch))
18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                continue;
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Create a buffer with only the arch slice date in it
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataExtractor arch_data;
19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        arch_data.SetData(data_buffer_sp);
19236da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::offset_t arch_data_offset = 0;
19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (arch_magic)
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
1971674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32:
1981674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32Swapped:
1991674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64:
2001674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64Swapped:
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic))
20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                return true;
20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileAtPathContainsArchAndUUID
21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
2140467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid
21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor data;
21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset = 0;
21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000));
22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0)
22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetData(data_buffer_sp);
22424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22536da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::offset_t data_offset = 0;
22624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t magic = data.GetU32(&data_offset);
22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (magic)
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // 32 bit mach-o file
2311674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32:
2321674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32Swapped:
2331674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64:
2341674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64Swapped:
23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // fat mach-o file
2381674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case UniversalMagic:
2391674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case UniversalMagicSwapped:
24024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
24124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        default:
24324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
24424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
24524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
24624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
24724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
24995b765e8000b44644d021e95bc58eac95028573bGreg ClaytonFileSpec
25095b765e8000b44644d021e95bc58eac95028573bGreg ClaytonSymbols::FindSymbolFileInBundle (const FileSpec& dsym_bundle_fspec,
25195b765e8000b44644d021e95bc58eac95028573bGreg Clayton                                 const lldb_private::UUID *uuid,
25295b765e8000b44644d021e95bc58eac95028573bGreg Clayton                                 const ArchSpec *arch)
25324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
25424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char path[PATH_MAX];
25524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec dsym_fspec;
25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
26252fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        lldb_utility::CleanUp <DIR *, int> dirp (opendir(path), NULL, closedir);
263ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton        if (dirp.is_valid())
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
265537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton            dsym_fspec.GetDirectory().SetCString(path);
26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            struct dirent* dp;
267ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton            while ((dp = readdir(dirp.get())) != NULL)
26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Only search directories
27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (dp->d_namlen == 1 && dp->d_name[0] == '.')
27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        continue;
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        continue;
27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
281537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                    dsym_fspec.GetFilename().SetCString(dp->d_name);
28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return dsym_fspec;
28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    dsym_fspec.Clear();
28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return dsym_fspec;
29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic int
29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerLocateMacOSXFilesUsingDebugSymbols
29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
295444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ModuleSpec &module_spec,
29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec *out_exec_fspec,   // If non-NULL, try and find the executable
29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec *out_dsym_fspec    // If non-NULL try and find the debug symbol file
29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int items_found = 0;
30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (out_exec_fspec)
30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        out_exec_fspec->Clear();
30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (out_dsym_fspec)
30624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        out_dsym_fspec->Clear();
30724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3083e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#if !defined (__arm__) // No DebugSymbols on the iOS devices
3093e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton
310444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
311444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
312444fe998bf707bd076a70c3a779db8575533695eGreg Clayton
31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (uuid && uuid->IsValid())
31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Try and locate the dSYM file using DebugSymbols first
31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes();
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (module_uuid != NULL)
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
3190fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton            CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes (NULL,
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[0],
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[1],
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[2],
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[3],
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[4],
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[5],
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[6],
32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[7],
32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[8],
32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[9],
33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[10],
33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[11],
33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[12],
33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[13],
33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[14],
33524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[15]));
33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (module_uuid_ref.get())
33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                CFCReleaser<CFURLRef> exec_url;
340444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (exec_fspec)
34224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char exec_cf_path[PATH_MAX];
34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path)))
34524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL,
34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  (const UInt8 *)exec_cf_path,
34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  strlen(exec_cf_path),
34824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  FALSE));
34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get()));
35224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                char path[PATH_MAX];
35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dsym_url.get())
35524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (out_dsym_fspec)
35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
3601b09dfef975addaa4aa330edb1dc7e28b8436028Jason Molenda                            out_dsym_fspec->SetFile(path, path[0] == '~');
36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory)
36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
36495b765e8000b44644d021e95bc58eac95028573bGreg Clayton                                *out_dsym_fspec = Symbols::FindSymbolFileInBundle (*out_dsym_fspec, uuid, arch);
36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                if (*out_dsym_fspec)
36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    ++items_found;
36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            else
36924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
37024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                ++items_found;
37124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
37224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
37324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
37424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
375964deba8853eb794e59263322b59b09b43669618Greg Clayton                    CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));
376964deba8853eb794e59263322b59b09b43669618Greg Clayton                    CFDictionaryRef uuid_dict = NULL;
377964deba8853eb794e59263322b59b09b43669618Greg Clayton                    if (dict.get())
37824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
379964deba8853eb794e59263322b59b09b43669618Greg Clayton                        char uuid_cstr_buf[64];
380964deba8853eb794e59263322b59b09b43669618Greg Clayton                        const char *uuid_cstr = uuid->GetAsCString (uuid_cstr_buf, sizeof(uuid_cstr_buf));
381964deba8853eb794e59263322b59b09b43669618Greg Clayton                        CFCString uuid_cfstr (uuid_cstr);
38263e5cf65c43615da20b272fde2a21ffd4fa6eb29Jason Molenda                        uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
383964deba8853eb794e59263322b59b09b43669618Greg Clayton                        if (uuid_dict)
38424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
385964deba8853eb794e59263322b59b09b43669618Greg Clayton
386964deba8853eb794e59263322b59b09b43669618Greg Clayton                            CFStringRef actual_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSourcePath")));
387964deba8853eb794e59263322b59b09b43669618Greg Clayton                            if (actual_src_cfpath)
38824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
389964deba8853eb794e59263322b59b09b43669618Greg Clayton                                CFStringRef build_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGBuildSourcePath")));
390964deba8853eb794e59263322b59b09b43669618Greg Clayton                                if (build_src_cfpath)
391b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                                {
392964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    char actual_src_path[PATH_MAX];
393964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    char build_src_path[PATH_MAX];
394964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    ::CFStringGetFileSystemRepresentation (actual_src_cfpath, actual_src_path, sizeof(actual_src_path));
395964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    ::CFStringGetFileSystemRepresentation (build_src_cfpath, build_src_path, sizeof(build_src_path));
3964d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                    if (actual_src_path[0] == '~')
3974d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                    {
3984d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                        FileSpec resolved_source_path(actual_src_path, true);
3994d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                        resolved_source_path.GetPath(actual_src_path, sizeof(actual_src_path));
4004d8c5434779393d5502b45f42a9371477604aab7Greg Clayton                                    }
401964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    module_spec.GetSourceMappingList().Append (ConstString(build_src_path), ConstString(actual_src_path), true);
402b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                                }
4030fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            }
4040fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                        }
405964deba8853eb794e59263322b59b09b43669618Greg Clayton                    }
406964deba8853eb794e59263322b59b09b43669618Greg Clayton
407964deba8853eb794e59263322b59b09b43669618Greg Clayton                    if (out_exec_fspec)
408964deba8853eb794e59263322b59b09b43669618Greg Clayton                    {
409964deba8853eb794e59263322b59b09b43669618Greg Clayton                        bool success = false;
410964deba8853eb794e59263322b59b09b43669618Greg Clayton                        if (uuid_dict)
411964deba8853eb794e59263322b59b09b43669618Greg Clayton                        {
412964deba8853eb794e59263322b59b09b43669618Greg Clayton                            CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable")));
413964deba8853eb794e59263322b59b09b43669618Greg Clayton                            if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
414964deba8853eb794e59263322b59b09b43669618Greg Clayton                            {
415964deba8853eb794e59263322b59b09b43669618Greg Clayton                                ++items_found;
416964deba8853eb794e59263322b59b09b43669618Greg Clayton                                out_exec_fspec->SetFile(path, path[0] == '~');
417964deba8853eb794e59263322b59b09b43669618Greg Clayton                                if (out_exec_fspec->Exists())
418964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    success = true;
419964deba8853eb794e59263322b59b09b43669618Greg Clayton                            }
420964deba8853eb794e59263322b59b09b43669618Greg Clayton                        }
4219ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton
4229ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton                        if (!success)
4230fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                        {
4240fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            // No dictionary, check near the dSYM bundle for an executable that matches...
4250fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
4260fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            {
4270fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                char *dsym_extension_pos = ::strstr (path, ".dSYM");
4280fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                if (dsym_extension_pos)
4290fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                {
4300fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    *dsym_extension_pos = '\0';
4310fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    FileSpec file_spec (path, true);
4320fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    switch (file_spec.GetFileType())
4330fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    {
4340fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeDirectory:  // Bundle directory?
4350fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            {
4360fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                CFCBundle bundle (path);
4370fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ());
4380fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                if (bundle_exe_url.get())
4390fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                {
4400fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1))
4410fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    {
4420fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        FileSpec bundle_exe_file_spec (path, true);
4430fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4440fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        if (FileAtPathContainsArchAndUUID (bundle_exe_file_spec, arch, uuid))
4450fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        {
4460fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                            ++items_found;
4470fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                            *out_exec_fspec = bundle_exe_file_spec;
4480fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        }
4490fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    }
4500fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                }
4510fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            }
4520fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4530fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4540fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypePipe:       // Forget pipes
4550fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeSocket:     // We can't process socket files
4560fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeInvalid:    // File doesn't exist...
4570fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4580fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4590fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeUnknown:
4600fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeRegular:
4610fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeSymbolicLink:
4620fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeOther:
4630fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            if (FileAtPathContainsArchAndUUID (file_spec, arch, uuid))
4640fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            {
4650fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                ++items_found;
4660fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                *out_exec_fspec = file_spec;
4670fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            }
4680fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4690fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    }
4700fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                }
47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
47424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
47624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
4783e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#endif // #if !defined (__arm__)
4793e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return items_found;
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
484444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonLocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec)
48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
486444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (exec_fspec)
48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
48924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char path[PATH_MAX];
49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (exec_fspec->GetPath(path, sizeof(path)))
49124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Make sure the module isn't already just a dSYM file...
49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                size_t obj_file_path_length = strlen(path);
49678c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                strlcat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
49778c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                strlcat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
499537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                dsym_fspec.SetFile(path, false);
50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
501444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
50224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    return true;
50424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
50524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
50624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    path[obj_file_path_length] = '\0';
50824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
50924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *last_dot = strrchr(path, '.');
51024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    while (last_dot != NULL && last_dot[0])
51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
51224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        char *next_slash = strchr(last_dot, '/');
51324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (next_slash != NULL)
51424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            *next_slash = '\0';
51678c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                            strlcat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
51778c180ab423d3a802566d49a41363b132f20c907Filipe Cabecinhas                            strlcat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
518537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                            dsym_fspec.SetFile(path, false);
519444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                            if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                return true;
52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            else
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                *last_dot = '\0';
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                char *prev_slash = strrchr(path, '/');
52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                if (prev_slash != NULL)
52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    *prev_slash = '\0';
52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                else
52824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    break;
52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        else
53224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
53324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            break;
53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
53524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
53724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
53824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
53924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    dsym_fspec.Clear();
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
54324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec
545444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonSymbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
547444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
548444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
549444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
55024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Timer scoped_timer (__PRETTY_FUNCTION__,
55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
553940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton                        arch ? arch->GetArchitectureName() : "<NULL>",
55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        uuid);
55524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec objfile_fspec;
557444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    if (exec_fspec && FileAtPathContainsArchAndUUID (exec_fspec, arch, uuid))
558444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        objfile_fspec = exec_fspec;
55924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
560444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL);
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return objfile_fspec;
56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec
565444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonSymbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
567444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
568444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
569444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
570444fe998bf707bd076a70c3a779db8575533695eGreg Clayton
57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Timer scoped_timer (__PRETTY_FUNCTION__,
57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        "LocateExecutableSymbolFile (file = %s, arch = %s, uuid = %p)",
57324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
574940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton                        arch ? arch->GetArchitectureName() : "<NULL>",
57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        uuid);
57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
57724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec symbol_fspec;
57824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // First try and find the dSYM in the same directory as the executable or in
57924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // an appropriate parent directory
580444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    if (LocateDSYMInVincinityOfExecutable (module_spec, symbol_fspec) == false)
58124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
58224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // We failed to easily find the dSYM above, so use DebugSymbols
583444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        LocateMacOSXFilesUsingDebugSymbols (module_spec, NULL, &symbol_fspec);
58424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
58524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return symbol_fspec;
58624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
587b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
588b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
589437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Claytonstatic bool
590437b5bccea45a5981edbbbeb4e23424aec4ce774Greg ClaytonGetModuleSpecInfoFromUUIDDictionary (CFDictionaryRef uuid_dict, ModuleSpec &module_spec)
591437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton{
592437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    bool success = false;
593437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    if (uuid_dict != NULL && CFGetTypeID (uuid_dict) == CFDictionaryGetTypeID ())
594437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    {
595437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        std::string str;
596437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        CFStringRef cf_str;
597437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
598437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSymbolRichExecutable"));
599437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
600437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
601437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (CFCString::FileSystemRepresentation(cf_str, str))
602437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                module_spec.GetFileSpec().SetFile (str.c_str(), true);
603437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
604437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
605437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGDSYMPath"));
606437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
607437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
608437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (CFCString::FileSystemRepresentation(cf_str, str))
609437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            {
610437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                module_spec.GetSymbolFileSpec().SetFile (str.c_str(), true);
611437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                success = true;
612437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            }
613437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
614437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
615437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGArchitecture"));
616437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
617437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
618437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (CFCString::FileSystemRepresentation(cf_str, str))
619437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                module_spec.GetArchitecture().SetTriple(str.c_str());
620437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
621437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
622437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        std::string DBGBuildSourcePath;
623437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        std::string DBGSourcePath;
624437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
625437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGBuildSourcePath"));
626437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
627437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
628437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            CFCString::FileSystemRepresentation(cf_str, DBGBuildSourcePath);
629437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
630437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
631437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        cf_str = (CFStringRef)CFDictionaryGetValue ((CFDictionaryRef) uuid_dict, CFSTR("DBGSourcePath"));
632437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (cf_str && CFGetTypeID (cf_str) == CFStringGetTypeID ())
633437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
634437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            CFCString::FileSystemRepresentation(cf_str, DBGSourcePath);
635437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
636437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
637437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty())
638437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        {
639437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            module_spec.GetSourceMappingList().Append (ConstString(DBGBuildSourcePath.c_str()), ConstString(DBGSourcePath.c_str()), true);
640437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton        }
641437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    }
642437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    return success;
643437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton}
644b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
645b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
646b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Claytonbool
647d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason MolendaSymbols::DownloadObjectAndSymbolFile (ModuleSpec &module_spec, bool force_lookup)
648b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton{
649b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    bool success = false;
650b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    const UUID *uuid_ptr = module_spec.GetUUIDPtr();
651437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    const FileSpec *file_spec_ptr = module_spec.GetFileSpecPtr();
652d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
653d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // It's expensive to check for the DBGShellCommands defaults setting, only do it once per
654d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // lldb run and cache the result.
655d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    static bool g_have_checked_for_dbgshell_command = false;
656d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    static const char *g_dbgshell_command = NULL;
657d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    if (g_have_checked_for_dbgshell_command == false)
658d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    {
659d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        g_have_checked_for_dbgshell_command = true;
660d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        CFTypeRef defaults_setting = CFPreferencesCopyAppValue (CFSTR ("DBGShellCommands"), CFSTR ("com.apple.DebugSymbols"));
661d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        if (defaults_setting && CFGetTypeID (defaults_setting) == CFStringGetTypeID())
662d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        {
663d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            char cstr_buf[PATH_MAX];
664d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            if (CFStringGetCString ((CFStringRef) defaults_setting, cstr_buf, sizeof (cstr_buf), kCFStringEncodingUTF8))
665d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            {
666d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda                g_dbgshell_command = strdup (cstr_buf);  // this malloc'ed memory will never be freed
667d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            }
668d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        }
669d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        if (defaults_setting)
670d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        {
671d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            CFRelease (defaults_setting);
672d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        }
673d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    }
674d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
675d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // When g_dbgshell_command is NULL, the user has not enabled the use of an external program
676d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    // to find the symbols, don't run it for them.
677d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    if (force_lookup == false && g_dbgshell_command == NULL)
678d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    {
679d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda        return false;
680d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda    }
681d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
682437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton    if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists()))
683b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    {
684b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        static bool g_located_dsym_for_uuid_exe = false;
685b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        static bool g_dsym_for_uuid_exe_exists = false;
686b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        static char g_dsym_for_uuid_exe_path[PATH_MAX];
687b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        if (!g_located_dsym_for_uuid_exe)
688b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        {
689b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            g_located_dsym_for_uuid_exe = true;
690b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            const char *dsym_for_uuid_exe_path_cstr = getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
691b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            FileSpec dsym_for_uuid_exe_spec;
692b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            if (dsym_for_uuid_exe_path_cstr)
693b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            {
694b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true);
695b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
696b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            }
697b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
698b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            if (!g_dsym_for_uuid_exe_exists)
699b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            {
700f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false);
701b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
702b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                if (!g_dsym_for_uuid_exe_exists)
703b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                {
70436da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton                    long bufsize;
705f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                    if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1)
706f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                    {
707f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        char buffer[bufsize];
708f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        struct passwd pwd;
709f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        struct passwd *tilde_rc = NULL;
710f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        // we are a library so we need to use the reentrant version of getpwnam()
711f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        if (getpwnam_r ("rc", &pwd, buffer, bufsize, &tilde_rc) == 0
712f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            && tilde_rc
713f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            && tilde_rc->pw_dir)
714f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        {
715f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            std::string dsymforuuid_path(tilde_rc->pw_dir);
716f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            dsymforuuid_path += "/bin/dsymForUUID";
717f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false);
718f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                            g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
719f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                        }
720f25697550690a7cda6a013c596fb8e6159b58256Jason Molenda                    }
721b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                }
722b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            }
723d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL)
724d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            {
725d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda                dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true);
726d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda                g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
727d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda            }
728d6d45ceeae51b6dbb9221a3cf82441afa212a7dcJason Molenda
729b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            if (g_dsym_for_uuid_exe_exists)
730b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                dsym_for_uuid_exe_spec.GetPath (g_dsym_for_uuid_exe_path, sizeof(g_dsym_for_uuid_exe_path));
731b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        }
732b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        if (g_dsym_for_uuid_exe_exists)
733b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        {
734b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            char uuid_cstr_buffer[64];
735437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            char file_path[PATH_MAX];
736437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            uuid_cstr_buffer[0] = '\0';
737437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            file_path[0] = '\0';
738437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            const char *uuid_cstr = NULL;
739437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
740437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (uuid_ptr)
741437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                uuid_cstr = uuid_ptr->GetAsCString(uuid_cstr_buffer, sizeof(uuid_cstr_buffer));
742437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
743437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (file_spec_ptr)
744437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                file_spec_ptr->GetPath(file_path, sizeof(file_path));
745437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
746437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            StreamString command;
747437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (uuid_cstr)
74863e5cf65c43615da20b272fde2a21ffd4fa6eb29Jason Molenda                command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, uuid_cstr);
749437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            else if (file_path && file_path[0])
75063e5cf65c43615da20b272fde2a21ffd4fa6eb29Jason Molenda                command.Printf("%s --ignoreNegativeCache --copyExecutable %s", g_dsym_for_uuid_exe_path, file_path);
751437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
752437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton            if (!command.GetString().empty())
753b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            {
754437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                int exit_status = -1;
755437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                int signo = -1;
756437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                std::string command_output;
757437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                Error error = Host::RunShellCommand (command.GetData(),
758437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     NULL,              // current working directory
759437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     &exit_status,      // Exit status
760437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     &signo,            // Signal int *
761437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     &command_output,   // Command output
762437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     30,                // Large timeout to allow for long dsym download times
763437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                     NULL);             // Don't run in a shell (we don't need shell expansion)
764437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                if (error.Success() && exit_status == 0 && !command_output.empty())
765b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                {
766437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                    CFCData data (CFDataCreateWithBytesNoCopy (NULL,
767437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                               (const UInt8 *)command_output.data(),
768437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                               command_output.size(),
769437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                               kCFAllocatorNull));
770437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
771437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                    CFCReleaser<CFDictionaryRef> plist((CFDictionaryRef)::CFPropertyListCreateFromXMLData (NULL, data.get(), kCFPropertyListImmutable, NULL));
772437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton
773437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                    if (CFGetTypeID (plist.get()) == CFDictionaryGetTypeID ())
774b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                    {
775437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                        if (uuid_cstr)
776b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        {
777437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            CFCString uuid_cfstr(uuid_cstr);
778437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            CFDictionaryRef uuid_dict = (CFDictionaryRef)CFDictionaryGetValue (plist.get(), uuid_cfstr.get());
779437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            success = GetModuleSpecInfoFromUUIDDictionary (uuid_dict, module_spec);
780b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        }
781437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                        else
782b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        {
783437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            const CFIndex num_values = ::CFDictionaryGetCount(plist.get());
784437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                            if (num_values > 0)
785b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                            {
786437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                std::vector<CFStringRef> keys (num_values, NULL);
787437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                std::vector<CFDictionaryRef> values (num_values, NULL);
788437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                ::CFDictionaryGetKeysAndValues(plist.get(), NULL, (const void **)&values[0]);
789437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                if (num_values == 1)
790437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                {
791437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    return GetModuleSpecInfoFromUUIDDictionary (values[0], module_spec);
792437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                }
793437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                else
794437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                {
795437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    for (CFIndex i=0; i<num_values; ++i)
796437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    {
797437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        ModuleSpec curr_module_spec;
798437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        if (GetModuleSpecInfoFromUUIDDictionary (values[i], curr_module_spec))
799437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        {
80040e278caddf5442776f9408f20d757cc85fe630aSean Callanan                                            if (module_spec.GetArchitecture().IsCompatibleMatch(curr_module_spec.GetArchitecture()))
801437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                            {
802437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                module_spec = curr_module_spec;
803437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                                return true;
804437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                            }
805437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                        }
806437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                    }
807437b5bccea45a5981edbbbeb4e23424aec4ce774Greg Clayton                                }
808b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                            }
809b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                        }
810b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                    }
811b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton                }
812b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton            }
813b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton        }
814b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    }
815b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton    return success;
816b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton}
817b924eb6c5250a9909dc55ac736d231f7ccae423bGreg Clayton
818