Symbols.cpp revision 964deba8853eb794e59263322b59b09b43669618
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>
141674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton#include "llvm/Support/MachO.h"
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes
1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include <CoreFoundation/CoreFoundation.h>
1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/ArchSpec.h"
2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataBuffer.h"
2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/DataExtractor.h"
24444fe998bf707bd076a70c3a779db8575533695eGreg Clayton#include "lldb/Core/Module.h"
2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Timer.h"
2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/UUID.h"
27cd548034fa23113e995b8463d14f910ba2f7298cGreg Clayton#include "lldb/Host/Endian.h"
28cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen#include "lldb/Host/Host.h"
29ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton#include "lldb/Utility/CleanUp.h"
30a1ebbd2410cafb890ab8519ae4e6b24cc618bd6aDaniel Dunbar#include "Host/macosx/cfcpp/CFCBundle.h"
3154e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton#include "Host/macosx/cfcpp/CFCReleaser.h"
32b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton#include "Host/macosx/cfcpp/CFCString.h"
335bc7b67ccc8bb4a977d129e51313067dcbc7bb94Chris Lattner#include "mach/machine.h"
3454e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton
350fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private;
381674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Claytonusing namespace llvm::MachO;
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
403e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#if !defined (__arm__) // No DebugSymbols on the iOS devices
4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerextern "C" {
4254e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerCFURLRef DBGCopyFullDSYMURLForUUID (CFUUIDRef uuid, CFURLRef exec_url);
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerCFDictionaryRef DBGCopyDSYMPropertyLists (CFURLRef dsym_url);
4554e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton
4654e7afa84d945f9137f9372ecde432f9e1a702fcGreg Clayton}
473e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#endif
4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerSkinnyMachOFileContainsArchAndUUID
5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
540467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid,   // the UUID we are looking for
5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset,
5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor& data,
5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t data_offset,
5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t magic
5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
611674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped);
621674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    if (magic == HeaderMagic32 || magic == HeaderMagic64)
63cd548034fa23113e995b8463d14f910ba2f7298cGreg Clayton        data.SetByteOrder (lldb::endian::InlHostByteOrder());
64cd548034fa23113e995b8463d14f910ba2f7298cGreg Clayton    else if (lldb::endian::InlHostByteOrder() == eByteOrderBig)
6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetByteOrder (eByteOrderLittle);
6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetByteOrder (eByteOrderBig);
6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t i;
7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t cputype      = data.GetU32(&data_offset);    // cpu specifier
7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t cpusubtype   = data.GetU32(&data_offset);    // machine specifier
7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    data_offset+=4; // Skip mach file type
7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t ncmds        = data.GetU32(&data_offset);    // number of load commands
7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t sizeofcmds   = data.GetU32(&data_offset);    // the size of all the load commands
7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    data_offset+=4; // Skip flags
7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Check the architecture if we have a valid arch pointer
7824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (arch)
7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
80cf0150574a0a97049efe2dce2cc0aa433705feb3Greg Clayton        ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype);
8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (file_arch != *arch)
8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return false;
8424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // The file exists, and if a valid arch pointer was passed in we know
8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // if already matches, so we can return if we aren't looking for a specific
8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // UUID
8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (uuid == NULL)
9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return true;
9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
921674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset += 4;   // Skip reserved field for in mach_header_64
9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Make sure we have enough data for all the load commands
961674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    if (magic == HeaderMagic64Swapped || magic == HeaderMagic64)
9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds)
9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds));
10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            data.SetData (data_buffer_sp);
10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds)
10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
10824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds));
10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            data.SetData (data_buffer_sp);
11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    for (i=0; i<ncmds; i++)
11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const uint32_t cmd_offset = data_offset;    // Save this data_offset in case parsing of the segment goes awry!
11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t cmd        = data.GetU32(&data_offset);
11724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t cmd_size   = data.GetU32(&data_offset);
1181674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        if (cmd == LoadCommandUUID)
11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
1200467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton            lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16);
121cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            if (file_uuid == *uuid)
122cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen                return true;
123cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen
124cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            // Emit some warning messages since the UUIDs do not match!
125cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            char path_buf[PATH_MAX];
126cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            path_buf[0] = '\0';
127cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf
128cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen                                                                     : file_spec.GetFilename().AsCString();
129cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            Host::SystemLog (Host::eSystemLogWarning,
130cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen                             "warning: UUID mismatch detected between binary and:\n\t'%s'\n",
131cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen                             path);
132cbf1591dd5b3d9d364d401bd857241bde198b645Johnny Chen            return false;
13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset = cmd_offset + cmd_size;
13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool
14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerUniversalMachOFileContainsArchAndUUID
14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
14224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
1440467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid,
14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset,
14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor& data,
14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t data_offset,
14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t magic
14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
1511674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton    assert(magic == UniversalMagic || magic == UniversalMagicSwapped);
15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Universal mach-o files always have their headers encoded as BIG endian
15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    data.SetByteOrder(eByteOrderBig);
15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    uint32_t i;
15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t nfat_arch = data.GetU32(&data_offset);   // number of structs that follow
15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch);
15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data.GetByteSize() < fat_header_and_arch_size)
16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size));
16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetData (data_buffer_sp);
16324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    for (i=0; i<nfat_arch; i++)
16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        cpu_type_t      arch_cputype        = data.GetU32(&data_offset);    // cpu specifier (int)
16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        cpu_subtype_t   arch_cpusubtype     = data.GetU32(&data_offset);    // machine specifier (int)
16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t        arch_offset         = data.GetU32(&data_offset);    // file offset to this object file
17024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  uint32_t        arch_size           = data.GetU32(&data_offset);    // size of this object file
17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    //  uint32_t        arch_align          = data.GetU32(&data_offset);    // alignment as a power of 2
17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data_offset += 8;   // Skip size and align as we don't need those
17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Only process this slice if the cpu type/subtype matches
17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (arch)
17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
176cf0150574a0a97049efe2dce2cc0aa433705feb3Greg Clayton            ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype);
17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (fat_arch != *arch)
17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                continue;
17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
18024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Create a buffer with only the arch slice date in it
18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataExtractor arch_data;
18324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000));
18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        arch_data.SetData(data_buffer_sp);
18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t arch_data_offset = 0;
18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t arch_magic = arch_data.GetU32(&arch_data_offset);
18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (arch_magic)
18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
1901674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32:
1911674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32Swapped:
1921674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64:
1931674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64Swapped:
19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic))
19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                return true;
19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileAtPathContainsArchAndUUID
20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec &file_spec,
20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch,
2070467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid
20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataExtractor data;
21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    off_t file_offset = 0;
21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000));
21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0)
21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        data.SetData(data_buffer_sp);
21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t data_offset = 0;
21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        uint32_t magic = data.GetU32(&data_offset);
22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        switch (magic)
22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // 32 bit mach-o file
2241674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32:
2251674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic32Swapped:
2261674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64:
2271674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case HeaderMagic64Swapped:
22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // fat mach-o file
2311674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case UniversalMagic:
2321674b12bbc3dae7b9543b8c5f958e90ddc767fa4Greg Clayton        case UniversalMagicSwapped:
23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic);
23424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        default:
23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            break;
23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
23924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
24024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
24124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic FileSpec
24324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerLocateDSYMMachFileInDSYMBundle
24424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
24524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const FileSpec& dsym_bundle_fspec,
2460467c78e9a75eff9ec33d3c1f39fa83e1c5d9241Greg Clayton    const lldb_private::UUID *uuid,
24724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const ArchSpec *arch)
24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
24924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    char path[PATH_MAX];
25024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec dsym_fspec;
25224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (dsym_bundle_fspec.GetPath(path, sizeof(path)))
25424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
25524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ::strncat (path, "/Contents/Resources/DWARF", sizeof(path) - strlen(path) - 1);
25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
25752fd984f7e67c3a0ab18d5565f40356bcfa84822Greg Clayton        lldb_utility::CleanUp <DIR *, int> dirp (opendir(path), NULL, closedir);
258ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton        if (dirp.is_valid())
25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
260537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton            dsym_fspec.GetDirectory().SetCString(path);
26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            struct dirent* dp;
262ad400274d4e3ed01a4c730e1d6f95e6cb2ac73dcGreg Clayton            while ((dp = readdir(dirp.get())) != NULL)
26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                // Only search directories
26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dp->d_type == DT_DIR || dp->d_type == DT_UNKNOWN)
26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (dp->d_namlen == 1 && dp->d_name[0] == '.')
26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        continue;
26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (dp->d_namlen == 2 && dp->d_name[0] == '.' && dp->d_name[1] == '.')
27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        continue;
27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dp->d_type == DT_REG || dp->d_type == DT_UNKNOWN)
27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
276537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                    dsym_fspec.GetFilename().SetCString(dp->d_name);
27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (FileAtPathContainsArchAndUUID (dsym_fspec, arch, uuid))
27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        return dsym_fspec;
27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    dsym_fspec.Clear();
28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return dsym_fspec;
28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic int
28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerLocateMacOSXFilesUsingDebugSymbols
28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner(
290444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ModuleSpec &module_spec,
29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec *out_exec_fspec,   // If non-NULL, try and find the executable
29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec *out_dsym_fspec    // If non-NULL try and find the debug symbol file
29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner)
29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    int items_found = 0;
29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (out_exec_fspec)
29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        out_exec_fspec->Clear();
29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (out_dsym_fspec)
30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        out_dsym_fspec->Clear();
30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
3033e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#if !defined (__arm__) // No DebugSymbols on the iOS devices
3043e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton
305444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
306444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
307444fe998bf707bd076a70c3a779db8575533695eGreg Clayton
30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (uuid && uuid->IsValid())
30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
31024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Try and locate the dSYM file using DebugSymbols first
31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const UInt8 *module_uuid = (const UInt8 *)uuid->GetBytes();
31224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (module_uuid != NULL)
31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
3140fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton            CFCReleaser<CFUUIDRef> module_uuid_ref(::CFUUIDCreateWithBytes (NULL,
31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[0],
31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[1],
31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[2],
31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[3],
31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[4],
32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[5],
32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[6],
32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[7],
32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[8],
32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[9],
32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[10],
32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[11],
32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[12],
32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[13],
32924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[14],
33024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                            module_uuid[15]));
33124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
33224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (module_uuid_ref.get())
33324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
33424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                CFCReleaser<CFURLRef> exec_url;
335444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
33624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (exec_fspec)
33724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
33824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char exec_cf_path[PATH_MAX];
33924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path)))
34024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_url.reset(::CFURLCreateFromFileSystemRepresentation (NULL,
34124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  (const UInt8 *)exec_cf_path,
34224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  strlen(exec_cf_path),
34324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                                                                  FALSE));
34424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
34524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                CFCReleaser<CFURLRef> dsym_url (::DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(), exec_url.get()));
34724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                char path[PATH_MAX];
34824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
34924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                if (dsym_url.get())
35024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
35124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    if (out_dsym_fspec)
35224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
35324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
35424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
355537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                            out_dsym_fspec->SetFile(path, false);
35624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
35724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            if (out_dsym_fspec->GetFileType () == FileSpec::eFileTypeDirectory)
35824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
35924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                *out_dsym_fspec = LocateDSYMMachFileInDSYMBundle (*out_dsym_fspec, uuid, arch);
36024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                if (*out_dsym_fspec)
36124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    ++items_found;
36224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
36324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            else
36424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
36524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                ++items_found;
36624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
36724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
36824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
36924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
370964deba8853eb794e59263322b59b09b43669618Greg Clayton                    CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));
371964deba8853eb794e59263322b59b09b43669618Greg Clayton                    CFDictionaryRef uuid_dict = NULL;
372964deba8853eb794e59263322b59b09b43669618Greg Clayton                    if (dict.get())
37324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
374964deba8853eb794e59263322b59b09b43669618Greg Clayton                        char uuid_cstr_buf[64];
375964deba8853eb794e59263322b59b09b43669618Greg Clayton                        const char *uuid_cstr = uuid->GetAsCString (uuid_cstr_buf, sizeof(uuid_cstr_buf));
376964deba8853eb794e59263322b59b09b43669618Greg Clayton                        CFCString uuid_cfstr (uuid_cstr);
377964deba8853eb794e59263322b59b09b43669618Greg Clayton                        CFDictionaryRef uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
378964deba8853eb794e59263322b59b09b43669618Greg Clayton                        if (uuid_dict)
37924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
380964deba8853eb794e59263322b59b09b43669618Greg Clayton
381964deba8853eb794e59263322b59b09b43669618Greg Clayton                            CFStringRef actual_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSourcePath")));
382964deba8853eb794e59263322b59b09b43669618Greg Clayton                            if (actual_src_cfpath)
38324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
384964deba8853eb794e59263322b59b09b43669618Greg Clayton                                CFStringRef build_src_cfpath = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGBuildSourcePath")));
385964deba8853eb794e59263322b59b09b43669618Greg Clayton                                if (build_src_cfpath)
386b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                                {
387964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    char actual_src_path[PATH_MAX];
388964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    char build_src_path[PATH_MAX];
389964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    ::CFStringGetFileSystemRepresentation (actual_src_cfpath, actual_src_path, sizeof(actual_src_path));
390964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    ::CFStringGetFileSystemRepresentation (build_src_cfpath, build_src_path, sizeof(build_src_path));
391964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    module_spec.GetSourceMappingList().Append (ConstString(build_src_path), ConstString(actual_src_path), true);
392b72d0f098e45936fa72e26b1a026c603e17e2d6cGreg Clayton                                }
3930fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            }
3940fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                        }
395964deba8853eb794e59263322b59b09b43669618Greg Clayton                    }
396964deba8853eb794e59263322b59b09b43669618Greg Clayton
397964deba8853eb794e59263322b59b09b43669618Greg Clayton                    if (out_exec_fspec)
398964deba8853eb794e59263322b59b09b43669618Greg Clayton                    {
399964deba8853eb794e59263322b59b09b43669618Greg Clayton                        bool success = false;
400964deba8853eb794e59263322b59b09b43669618Greg Clayton                        if (uuid_dict)
401964deba8853eb794e59263322b59b09b43669618Greg Clayton                        {
402964deba8853eb794e59263322b59b09b43669618Greg Clayton                            CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable")));
403964deba8853eb794e59263322b59b09b43669618Greg Clayton                            if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
404964deba8853eb794e59263322b59b09b43669618Greg Clayton                            {
405964deba8853eb794e59263322b59b09b43669618Greg Clayton                                ++items_found;
406964deba8853eb794e59263322b59b09b43669618Greg Clayton                                out_exec_fspec->SetFile(path, path[0] == '~');
407964deba8853eb794e59263322b59b09b43669618Greg Clayton                                if (out_exec_fspec->Exists())
408964deba8853eb794e59263322b59b09b43669618Greg Clayton                                    success = true;
409964deba8853eb794e59263322b59b09b43669618Greg Clayton                            }
410964deba8853eb794e59263322b59b09b43669618Greg Clayton                        }
4119ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton
4129ce953807eb814a93b449dc243de4f7bf32c3115Greg Clayton                        if (!success)
4130fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                        {
4140fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            // No dictionary, check near the dSYM bundle for an executable that matches...
4150fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            if (::CFURLGetFileSystemRepresentation (dsym_url.get(), true, (UInt8*)path, sizeof(path)-1))
4160fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                            {
4170fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                char *dsym_extension_pos = ::strstr (path, ".dSYM");
4180fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                if (dsym_extension_pos)
4190fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                {
4200fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    *dsym_extension_pos = '\0';
4210fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    FileSpec file_spec (path, true);
4220fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    switch (file_spec.GetFileType())
4230fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    {
4240fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeDirectory:  // Bundle directory?
4250fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            {
4260fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                CFCBundle bundle (path);
4270fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                CFCReleaser<CFURLRef> bundle_exe_url (bundle.CopyExecutableURL ());
4280fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                if (bundle_exe_url.get())
4290fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                {
4300fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    if (::CFURLGetFileSystemRepresentation (bundle_exe_url.get(), true, (UInt8*)path, sizeof(path)-1))
4310fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    {
4320fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        FileSpec bundle_exe_file_spec (path, true);
4330fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4340fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        if (FileAtPathContainsArchAndUUID (bundle_exe_file_spec, arch, uuid))
4350fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        {
4360fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                            ++items_found;
4370fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                            *out_exec_fspec = bundle_exe_file_spec;
4380fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                        }
4390fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                    }
4400fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                }
4410fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            }
4420fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4430fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4440fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypePipe:       // Forget pipes
4450fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeSocket:     // We can't process socket files
4460fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeInvalid:    // File doesn't exist...
4470fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4480fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton
4490fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeUnknown:
4500fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeRegular:
4510fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeSymbolicLink:
4520fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                        case FileSpec::eFileTypeOther:
4530fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            if (FileAtPathContainsArchAndUUID (file_spec, arch, uuid))
4540fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            {
4550fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                ++items_found;
4560fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                                *out_exec_fspec = file_spec;
4570fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            }
4580fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                            break;
4590fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                    }
4600fa512447e00da09d300fbabd18b5ce94f52fdaaGreg Clayton                                }
46124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
46224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
46324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
46424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
46524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
46624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
46724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
4683e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton#endif // #if !defined (__arm__)
4693e4238d47a6d1a3106f357d2e7b495870721c7aeGreg Clayton
47024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return items_found;
47124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
47224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
47324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerstatic bool
474444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonLocateDSYMInVincinityOfExecutable (const ModuleSpec &module_spec, FileSpec &dsym_fspec)
47524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
476444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
47724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (exec_fspec)
47824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
47924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        char path[PATH_MAX];
48024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (exec_fspec->GetPath(path, sizeof(path)))
48124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
48224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Make sure the module isn't already just a dSYM file...
48324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL)
48424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            {
48524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                size_t obj_file_path_length = strlen(path);
48624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
48724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
48824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
489537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                dsym_fspec.SetFile(path, false);
49024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
491444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
49224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
49324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    return true;
49424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
49524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                else
49624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                {
49724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    path[obj_file_path_length] = '\0';
49824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
49924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    char *last_dot = strrchr(path, '.');
50024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    while (last_dot != NULL && last_dot[0])
50124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    {
50224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        char *next_slash = strchr(last_dot, '/');
50324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        if (next_slash != NULL)
50424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
50524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            *next_slash = '\0';
50624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            strncat(path, ".dSYM/Contents/Resources/DWARF/", sizeof(path));
50724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            strncat(path, exec_fspec->GetFilename().AsCString(), sizeof(path));
508537a7a86687683fd403ce652d178fbc89e06ef9fGreg Clayton                            dsym_fspec.SetFile(path, false);
509444fe998bf707bd076a70c3a779db8575533695eGreg Clayton                            if (dsym_fspec.Exists() && FileAtPathContainsArchAndUUID (dsym_fspec, module_spec.GetArchitecturePtr(), module_spec.GetUUIDPtr()))
51024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                return true;
51124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            else
51224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            {
51324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                *last_dot = '\0';
51424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                char *prev_slash = strrchr(path, '/');
51524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                if (prev_slash != NULL)
51624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    *prev_slash = '\0';
51724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                else
51824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                                    break;
51924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            }
52024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
52124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        else
52224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        {
52324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                            break;
52424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        }
52524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                    }
52624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                }
52724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            }
52824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
52924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
53024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    dsym_fspec.Clear();
53124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return false;
53224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
53324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
53424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec
535444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonSymbols::LocateExecutableObjectFile (const ModuleSpec &module_spec)
53624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
537444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
538444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
539444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
54024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Timer scoped_timer (__PRETTY_FUNCTION__,
54124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)",
54224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
543940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton                        arch ? arch->GetArchitectureName() : "<NULL>",
54424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        uuid);
54524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
54624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec objfile_fspec;
547444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    if (exec_fspec && FileAtPathContainsArchAndUUID (exec_fspec, arch, uuid))
548444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        objfile_fspec = exec_fspec;
54924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    else
550444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        LocateMacOSXFilesUsingDebugSymbols (module_spec, &objfile_fspec, NULL);
55124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return objfile_fspec;
55224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
55324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
55424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerFileSpec
555444fe998bf707bd076a70c3a779db8575533695eGreg ClaytonSymbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
55624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
557444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
558444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const ArchSpec *arch = module_spec.GetArchitecturePtr();
559444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    const UUID *uuid = module_spec.GetUUIDPtr();
560444fe998bf707bd076a70c3a779db8575533695eGreg Clayton
56124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    Timer scoped_timer (__PRETTY_FUNCTION__,
56224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        "LocateExecutableSymbolFile (file = %s, arch = %s, uuid = %p)",
56324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        exec_fspec ? exec_fspec->GetFilename().AsCString ("<NULL>") : "<NULL>",
564940b103224f3062578c7a7e6e76d8bf4a7956f2aGreg Clayton                        arch ? arch->GetArchitectureName() : "<NULL>",
56524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner                        uuid);
56624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
56724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    FileSpec symbol_fspec;
56824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // First try and find the dSYM in the same directory as the executable or in
56924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // an appropriate parent directory
570444fe998bf707bd076a70c3a779db8575533695eGreg Clayton    if (LocateDSYMInVincinityOfExecutable (module_spec, symbol_fspec) == false)
57124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
57224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // We failed to easily find the dSYM above, so use DebugSymbols
573444fe998bf707bd076a70c3a779db8575533695eGreg Clayton        LocateMacOSXFilesUsingDebugSymbols (module_spec, NULL, &symbol_fspec);
57424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
57524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return symbol_fspec;
57624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
577