Added the ability to get the SDK path for a target using the platform plugins. If LLDB lives inside an Xcode.app bundle, it will select the SDK in the Xcode bundle, else it will use the currently selected Xcode.

Also added the DWARFDataExtractor classes to the Xcode project file.

llvm-svn: 193380
This commit is contained in:
Greg Clayton 2013-10-24 22:54:08 +00:00
parent 28c7a21b29
commit 9b2349888f
7 changed files with 295 additions and 1 deletions

View File

@ -640,6 +640,72 @@ public:
}
return 0;
}
//------------------------------------------------------------------
/// Get the minimum OS version this object file can run on.
///
/// Some object files have information that specifies the minimum OS
/// version that they can be used on.
///
/// If \a versions is NULL, or if \a num_versions is 0, the return
/// value will indicate how many version numbers are available in
/// this object file. Then a subsequent call can be made to this
/// function with a value of \a versions and \a num_versions that
/// has enough storage to store some or all version numbers.
///
/// @param[out] versions
/// A pointer to an array of uint32_t types that is \a num_versions
/// long. If this value is NULL, the return value will indicate
/// how many version numbers are required for a subsequent call
/// to this function so that all versions can be retrieved. If
/// the value is non-NULL, then at most \a num_versions of the
/// existing versions numbers will be filled into \a versions.
/// If there is no version information available, \a versions
/// will be filled with \a num_versions UINT32_MAX values
/// and zero will be returned.
///
/// @param[in] num_versions
/// The maximum number of entries to fill into \a versions. If
/// this value is zero, then the return value will indicate
/// how many version numbers there are in total so another call
/// to this function can be make with adequate storage in
/// \a versions to get all of the version numbers. If \a
/// num_versions is less than the actual number of version
/// numbers in this object file, only \a num_versions will be
/// filled into \a versions (if \a versions is non-NULL).
///
/// @return
/// This function always returns the number of version numbers
/// that this object file has regardless of the number of
/// version numbers that were copied into \a versions.
//------------------------------------------------------------------
virtual uint32_t
GetMinimumOSVersion (uint32_t *versions, uint32_t num_versions)
{
if (versions && num_versions)
{
for (uint32_t i=0; i<num_versions; ++i)
versions[i] = UINT32_MAX;
}
return 0;
}
//------------------------------------------------------------------
/// Get the SDK OS version this object file was built with.
///
/// The versions arguments and returns values are the same as the
/// GetMinimumOSVersion()
//------------------------------------------------------------------
virtual uint32_t
GetSDKVersion (uint32_t *versions, uint32_t num_versions)
{
if (versions && num_versions)
{
for (uint32_t i=0; i<num_versions; ++i)
versions[i] = UINT32_MAX;
}
return 0;
}
//------------------------------------------------------------------
// Member Functions

View File

@ -460,6 +460,15 @@ namespace lldb_private {
virtual lldb::BreakpointSP
SetThreadCreationBreakpoint (Target &target);
//------------------------------------------------------------------
// Given a target, find the local SDK directory if one exists on the
// current host.
//------------------------------------------------------------------
virtual lldb_private::ConstString
GetSDKDirectory (lldb_private::Target &target)
{
return lldb_private::ConstString();
}
const std::string &
GetRemoteURL () const

View File

@ -427,6 +427,8 @@
26A527C414E24F5F00F3A14A /* ThreadMachCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 26A527C014E24F5F00F3A14A /* ThreadMachCore.h */; };
26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C6886E137880C400407EDF /* RegisterValue.cpp */; };
26A7A035135E6E4200FB369E /* OptionValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A7A034135E6E4200FB369E /* OptionValue.cpp */; };
26AB92121819D74600E63F3E /* DWARFDataExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26AB92101819D74600E63F3E /* DWARFDataExtractor.cpp */; };
26AB92131819D74600E63F3E /* DWARFDataExtractor.h in Headers */ = {isa = PBXBuildFile; fileRef = 26AB92111819D74600E63F3E /* DWARFDataExtractor.h */; };
26ACEC2815E077AE00E94760 /* Property.h in Headers */ = {isa = PBXBuildFile; fileRef = 26ACEC2715E077AE00E94760 /* Property.h */; };
26B1EFAE154638AF00E2DAC7 /* DWARFDeclContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26B1EFAC154638AF00E2DAC7 /* DWARFDeclContext.cpp */; };
26B1EFAF154638AF00E2DAC7 /* DWARFDeclContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 26B1EFAD154638AF00E2DAC7 /* DWARFDeclContext.h */; };
@ -1081,6 +1083,8 @@
26A527C014E24F5F00F3A14A /* ThreadMachCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadMachCore.h; sourceTree = "<group>"; };
26A7A034135E6E4200FB369E /* OptionValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionValue.cpp; path = source/Interpreter/OptionValue.cpp; sourceTree = "<group>"; };
26A7A036135E6E5300FB369E /* OptionValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionValue.h; path = include/lldb/Interpreter/OptionValue.h; sourceTree = "<group>"; };
26AB92101819D74600E63F3E /* DWARFDataExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDataExtractor.cpp; sourceTree = "<group>"; };
26AB92111819D74600E63F3E /* DWARFDataExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFDataExtractor.h; sourceTree = "<group>"; };
26ACEC2715E077AE00E94760 /* Property.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Property.h; path = include/lldb/Interpreter/Property.h; sourceTree = "<group>"; };
26B167A41123BF5500DC7B4F /* ThreadSafeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeValue.h; path = include/lldb/Core/ThreadSafeValue.h; sourceTree = "<group>"; };
26B1EFAC154638AF00E2DAC7 /* DWARFDeclContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFDeclContext.cpp; sourceTree = "<group>"; };
@ -2036,6 +2040,8 @@
260C89B610F57C5600BB2B04 /* DWARFAttribute.h */,
260C89B710F57C5600BB2B04 /* DWARFCompileUnit.cpp */,
260C89B810F57C5600BB2B04 /* DWARFCompileUnit.h */,
26AB92101819D74600E63F3E /* DWARFDataExtractor.cpp */,
26AB92111819D74600E63F3E /* DWARFDataExtractor.h */,
260C89B910F57C5600BB2B04 /* DWARFDebugAbbrev.cpp */,
260C89BA10F57C5600BB2B04 /* DWARFDebugAbbrev.h */,
260C89BB10F57C5600BB2B04 /* DWARFDebugAranges.cpp */,
@ -3584,6 +3590,7 @@
AF254E32170CCC33007AE5C9 /* PlatformDarwinKernel.h in Headers */,
2694E99E14FC0BB30076DE67 /* PlatformFreeBSD.h in Headers */,
2694E9A514FC0BBD0076DE67 /* PlatformLinux.h in Headers */,
26AB92131819D74600E63F3E /* DWARFDataExtractor.h in Headers */,
2663E379152BD1890091EC22 /* ReadWriteLock.h in Headers */,
945759681534941F005A9070 /* PlatformPOSIX.h in Headers */,
26B1EFAF154638AF00E2DAC7 /* DWARFDeclContext.h in Headers */,
@ -4193,6 +4200,7 @@
268900E613353E6F00698AC0 /* Variable.cpp in Sources */,
268900E713353E6F00698AC0 /* VariableList.cpp in Sources */,
268900E813353E6F00698AC0 /* ABI.cpp in Sources */,
26AB92121819D74600E63F3E /* DWARFDataExtractor.cpp in Sources */,
268900E913353E6F00698AC0 /* CPPLanguageRuntime.cpp in Sources */,
268900EA13353E6F00698AC0 /* DynamicLoader.cpp in Sources */,
268900EB13353E6F00698AC0 /* ExecutionContext.cpp in Sources */,

View File

@ -4516,6 +4516,130 @@ ObjectFileMachO::GetLLDBSharedCacheUUID ()
return uuid;
}
uint32_t
ObjectFileMachO::GetMinimumOSVersion (uint32_t *versions, uint32_t num_versions)
{
if (m_min_os_versions.empty())
{
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
bool success = false;
for (uint32_t i=0; success == false && i < m_header.ncmds; ++i)
{
const lldb::offset_t load_cmd_offset = offset;
version_min_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL)
break;
if (lc.cmd == LC_VERSION_MIN_MACOSX || lc.cmd == LC_VERSION_MIN_IPHONEOS)
{
if (m_data.GetU32 (&offset, &lc.version, (sizeof(lc) / sizeof(uint32_t)) - 2))
{
const uint32_t xxxx = lc.version >> 16;
const uint32_t yy = (lc.version >> 8) & 0xffu;
const uint32_t zz = lc.version & 0xffu;
if (xxxx)
{
m_min_os_versions.push_back(xxxx);
if (yy)
{
m_min_os_versions.push_back(yy);
if (zz)
m_min_os_versions.push_back(zz);
}
}
success = true;
}
}
offset = load_cmd_offset + lc.cmdsize;
}
if (success == false)
{
// Push an invalid value so we don't keep trying to
m_min_os_versions.push_back(UINT32_MAX);
}
}
if (m_min_os_versions.size() > 1 || m_min_os_versions[0] != UINT32_MAX)
{
if (versions != NULL && num_versions > 0)
{
for (size_t i=0; i<num_versions; ++i)
{
if (i < m_min_os_versions.size())
versions[i] = m_min_os_versions[i];
else
versions[i] = 0;
}
}
return m_min_os_versions.size();
}
// Call the superclasses version that will empty out the data
return ObjectFile::GetMinimumOSVersion (versions, num_versions);
}
uint32_t
ObjectFileMachO::GetSDKVersion(uint32_t *versions, uint32_t num_versions)
{
if (m_sdk_versions.empty())
{
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
bool success = false;
for (uint32_t i=0; success == false && i < m_header.ncmds; ++i)
{
const lldb::offset_t load_cmd_offset = offset;
version_min_command lc;
if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL)
break;
if (lc.cmd == LC_VERSION_MIN_MACOSX || lc.cmd == LC_VERSION_MIN_IPHONEOS)
{
if (m_data.GetU32 (&offset, &lc.version, (sizeof(lc) / sizeof(uint32_t)) - 2))
{
const uint32_t xxxx = lc.reserved >> 16;
const uint32_t yy = (lc.reserved >> 8) & 0xffu;
const uint32_t zz = lc.reserved & 0xffu;
if (xxxx)
{
m_sdk_versions.push_back(xxxx);
if (yy)
{
m_sdk_versions.push_back(yy);
if (zz)
m_sdk_versions.push_back(zz);
}
}
success = true;
}
}
offset = load_cmd_offset + lc.cmdsize;
}
if (success == false)
{
// Push an invalid value so we don't keep trying to
m_sdk_versions.push_back(UINT32_MAX);
}
}
if (m_sdk_versions.size() > 1 || m_sdk_versions[0] != UINT32_MAX)
{
if (versions != NULL && num_versions > 0)
{
for (size_t i=0; i<num_versions; ++i)
{
if (i < m_sdk_versions.size())
versions[i] = m_sdk_versions[i];
else
versions[i] = 0;
}
}
return m_sdk_versions.size();
}
// Call the superclasses version that will empty out the data
return ObjectFile::GetSDKVersion (versions, num_versions);
}
//------------------------------------------------------------------
// PluginInterface protocol

View File

@ -152,6 +152,12 @@ public:
virtual uint32_t
GetVersion (uint32_t *versions, uint32_t num_versions);
virtual uint32_t
GetMinimumOSVersion (uint32_t *versions, uint32_t num_versions);
virtual uint32_t
GetSDKVersion (uint32_t *versions, uint32_t num_versions);
protected:
static bool
@ -192,6 +198,8 @@ protected:
llvm::MachO::dysymtab_command m_dysymtab;
std::vector<llvm::MachO::segment_command_64> m_mach_segments;
std::vector<llvm::MachO::section_64> m_mach_sections;
std::vector<uint32_t> m_min_os_versions;
std::vector<uint32_t> m_sdk_versions;
typedef lldb_private::RangeVector<uint32_t, uint32_t> FileRangeArray;
lldb_private::Address m_entry_point_address;
FileRangeArray m_thread_context_offsets;

View File

@ -31,6 +31,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@ -165,8 +166,83 @@ PlatformMacOSX::~PlatformMacOSX()
{
}
ConstString
PlatformMacOSX::GetSDKDirectory (lldb_private::Target &target)
{
ModuleSP exe_module_sp (target.GetExecutableModule());
if (exe_module_sp)
{
ObjectFile *objfile = exe_module_sp->GetObjectFile();
if (objfile)
{
std::string xcode_contents_path;
std::string default_xcode_sdk;
FileSpec fspec;
uint32_t versions[2];
if (objfile->GetSDKVersion(versions, sizeof(versions)))
{
if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, fspec))
{
std::string path;
xcode_contents_path = fspec.GetPath();
size_t pos = xcode_contents_path.find("/Xcode.app/Contents/");
if (pos != std::string::npos)
{
// LLDB.framework is inside an Xcode app bundle, we can locate the SDK from here
xcode_contents_path.erase(pos + strlen("/Xcode.app/Contents/"));
}
else
{
xcode_contents_path.clear();
// Use the selected Xcode
int status = 0;
int signo = 0;
std::string output;
const char *command = "xcrun -sdk macosx --show-sdk-path";
lldb_private::Error error = RunShellCommand (command, // shell command to run
NULL, // current working directory
&status, // Put the exit status of the process in here
&signo, // Put the signal that caused the process to exit in here
&output, // Get the output from the command and place it in this string
3); // Timeout in seconds to wait for shell program to finish
if (status == 0 && !output.empty())
{
size_t first_non_newline = output.find_last_not_of("\r\n");
if (first_non_newline != std::string::npos)
output.erase(first_non_newline+1);
default_xcode_sdk = output;
pos = default_xcode_sdk.find("/Xcode.app/Contents/");
if (pos != std::string::npos)
xcode_contents_path = default_xcode_sdk.substr(0, pos + strlen("/Xcode.app/Contents/"));
}
}
}
if (!xcode_contents_path.empty())
{
StreamString sdk_path;
sdk_path.Printf("%sDeveloper/Platforms/MacOSX.platform/Developer/SDKs/MacOSX%u.%u.sdk", xcode_contents_path.c_str(), versions[0], versions[1]);
fspec.SetFile(sdk_path.GetString().c_str(), false);
if (fspec.Exists())
return ConstString(sdk_path.GetString().c_str());
}
if (!default_xcode_sdk.empty())
{
fspec.SetFile(default_xcode_sdk.c_str(), false);
if (fspec.Exists())
return ConstString(default_xcode_sdk.c_str());
}
}
}
}
return ConstString();
}
Error
PlatformMacOSX::GetSymbolFile (const FileSpec &platform_file,
PlatformMacOSX::GetSymbolFile (const FileSpec &platform_file,
const UUID *uuid_ptr,
FileSpec &local_file)
{

View File

@ -95,6 +95,9 @@ public:
GetSupportedArchitectureAtIndex (uint32_t idx,
lldb_private::ArchSpec &arch);
virtual lldb_private::ConstString
GetSDKDirectory (lldb_private::Target &target);
private:
DISALLOW_COPY_AND_ASSIGN (PlatformMacOSX);