2011-03-24 12:28:38 +08:00
//===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "PlatformDarwin.h"
// C Includes
2015-11-05 02:10:31 +08:00
# include <string.h>
2011-03-24 12:28:38 +08:00
// C++ Includes
2015-11-05 02:10:31 +08:00
# include <algorithm>
2015-10-20 05:43:07 +08:00
# include <mutex>
2011-03-24 12:28:38 +08:00
// Other libraries and framework includes
2015-03-04 07:11:11 +08:00
# include "clang/Basic/VersionTuple.h"
2011-03-24 12:28:38 +08:00
// Project includes
# include "lldb/Breakpoint/BreakpointLocation.h"
2015-03-05 01:43:00 +08:00
# include "lldb/Breakpoint/BreakpointSite.h"
2011-04-12 13:54:46 +08:00
# include "lldb/Core/Debugger.h"
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-30 05:13:06 +08:00
# include "lldb/Core/Module.h"
# include "lldb/Core/ModuleSpec.h"
2011-03-24 12:28:38 +08:00
# include "lldb/Host/Host.h"
2014-08-21 00:42:51 +08:00
# include "lldb/Host/HostInfo.h"
2016-09-07 04:57:50 +08:00
# include "lldb/Host/Symbols.h"
2015-11-06 06:33:17 +08:00
# include "lldb/Host/XML.h"
2015-02-26 09:37:26 +08:00
# include "lldb/Interpreter/CommandInterpreter.h"
<rdar://problem/11757916>
Make breakpoint setting by file and line much more efficient by only looking for inlined breakpoint locations if we are setting a breakpoint in anything but a source implementation file. Implementing this complex for a many reasons. Turns out that parsing compile units lazily had some issues with respect to how we need to do things with DWARF in .o files. So the fixes in the checkin for this makes these changes:
- Add a new setting called "target.inline-breakpoint-strategy" which can be set to "never", "always", or "headers". "never" will never try and set any inlined breakpoints (fastest). "always" always looks for inlined breakpoint locations (slowest, but most accurate). "headers", which is the default setting, will only look for inlined breakpoint locations if the breakpoint is set in what are consudered to be header files, which is realy defined as "not in an implementation source file".
- modify the breakpoint setting by file and line to check the current "target.inline-breakpoint-strategy" setting and act accordingly
- Modify compile units to be able to get their language and other info lazily. This allows us to create compile units from the debug map and not have to fill all of the details in, and then lazily discover this information as we go on debuggging. This is needed to avoid parsing all .o files when setting breakpoints in implementation only files (no inlines). Otherwise we would need to parse the .o file, the object file (mach-o in our case) and the symbol file (DWARF in the object file) just to see what the compile unit was.
- modify the "SymbolFileDWARFDebugMap" to subclass lldb_private::Module so that the virtual "GetObjectFile()" and "GetSymbolVendor()" functions can be intercepted when the .o file contenst are later lazilly needed. Prior to this fix, when we first instantiated the "SymbolFileDWARFDebugMap" class, we would also make modules, object files and symbol files for every .o file in the debug map because we needed to fix up the sections in the .o files with information that is in the executable debug map. Now we lazily do this in the DebugMapModule::GetObjectFile()
Cleaned up header includes a bit as well.
llvm-svn: 162860
2012-08-30 05:13:06 +08:00
# include "lldb/Symbol/ObjectFile.h"
2013-01-12 07:44:27 +08:00
# include "lldb/Symbol/SymbolFile.h"
# include "lldb/Symbol/SymbolVendor.h"
2017-06-02 13:17:19 +08:00
# include "lldb/Target/Platform.h"
2015-11-06 06:33:17 +08:00
# include "lldb/Target/Process.h"
2011-03-24 12:28:38 +08:00
# include "lldb/Target/Target.h"
2017-03-07 07:42:14 +08:00
# include "lldb/Utility/DataBufferLLVM.h"
2017-03-04 04:56:28 +08:00
# include "lldb/Utility/Log.h"
2017-05-12 12:51:55 +08:00
# include "lldb/Utility/Status.h"
2017-06-29 22:32:17 +08:00
# include "lldb/Utility/Timer.h"
2014-06-27 13:17:41 +08:00
# include "llvm/ADT/STLExtras.h"
2017-03-09 01:56:08 +08:00
# include "llvm/Support/FileSystem.h"
2017-02-07 01:55:02 +08:00
# include "llvm/Support/Threading.h"
2011-03-24 12:28:38 +08:00
2016-09-07 04:57:50 +08:00
# if defined(__APPLE__)
2015-11-21 12:00:43 +08:00
# include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
# endif
2011-03-24 12:28:38 +08:00
using namespace lldb ;
using namespace lldb_private ;
//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
PlatformDarwin : : PlatformDarwin ( bool is_host )
: PlatformPOSIX ( is_host ) , // This is the local host platform
m_developer_directory ( ) { }
2011-03-24 12:28:38 +08:00
//------------------------------------------------------------------
/// Destructor.
///
/// The destructor is virtual since this class is designed to be
/// inherited from by the plug-in instance.
//------------------------------------------------------------------
2016-09-07 04:57:50 +08:00
PlatformDarwin : : ~ PlatformDarwin ( ) { }
FileSpecList PlatformDarwin : : LocateExecutableScriptingResources (
Target * target , Module & module , Stream * feedback_stream ) {
FileSpecList file_list ;
if ( target & &
target - > GetDebugger ( ) . GetScriptLanguage ( ) = = eScriptLanguagePython ) {
// NB some extensions might be meaningful and should not be stripped -
// "this.binary.file"
// should not lose ".file" but GetFileNameStrippingExtension() will do
// precisely that.
// Ideally, we should have a per-platform list of extensions (".exe",
// ".app", ".dSYM", ".framework")
// which should be stripped while leaving "this.binary.file" as-is.
ScriptInterpreter * script_interpreter =
target - > GetDebugger ( ) . GetCommandInterpreter ( ) . GetScriptInterpreter ( ) ;
FileSpec module_spec = module . GetFileSpec ( ) ;
if ( module_spec ) {
SymbolVendor * symbols = module . GetSymbolVendor ( ) ;
if ( symbols ) {
SymbolFile * symfile = symbols - > GetSymbolFile ( ) ;
if ( symfile ) {
ObjectFile * objfile = symfile - > GetObjectFile ( ) ;
if ( objfile ) {
FileSpec symfile_spec ( objfile - > GetFileSpec ( ) ) ;
if ( symfile_spec & & symfile_spec . Exists ( ) ) {
while ( module_spec . GetFilename ( ) ) {
std : : string module_basename (
module_spec . GetFilename ( ) . GetCString ( ) ) ;
std : : string original_module_basename ( module_basename ) ;
bool was_keyword = false ;
// FIXME: for Python, we cannot allow certain characters in
// module
// filenames we import. Theoretically, different scripting
// languages may
// have different sets of forbidden tokens in filenames, and
// that should
// be dealt with by each ScriptInterpreter. For now, we just
// replace dots
// with underscores, but if we ever support anything other than
// Python
// we will need to rework this
std : : replace ( module_basename . begin ( ) , module_basename . end ( ) ,
' . ' , ' _ ' ) ;
std : : replace ( module_basename . begin ( ) , module_basename . end ( ) ,
' ' , ' _ ' ) ;
std : : replace ( module_basename . begin ( ) , module_basename . end ( ) ,
' - ' , ' _ ' ) ;
if ( script_interpreter & &
script_interpreter - > IsReservedWord (
module_basename . c_str ( ) ) ) {
module_basename . insert ( module_basename . begin ( ) , ' _ ' ) ;
was_keyword = true ;
}
2011-03-24 12:28:38 +08:00
2016-09-07 04:57:50 +08:00
StreamString path_string ;
StreamString original_path_string ;
// for OSX we are going to be in
// .dSYM/Contents/Resources/DWARF/<basename>
// let us go to .dSYM/Contents/Resources/Python/<basename>.py
// and see if the file exists
path_string . Printf ( " %s/../Python/%s.py " ,
symfile_spec . GetDirectory ( ) . GetCString ( ) ,
module_basename . c_str ( ) ) ;
original_path_string . Printf (
" %s/../Python/%s.py " ,
symfile_spec . GetDirectory ( ) . GetCString ( ) ,
original_module_basename . c_str ( ) ) ;
2016-11-17 05:15:24 +08:00
FileSpec script_fspec ( path_string . GetString ( ) , true ) ;
FileSpec orig_script_fspec ( original_path_string . GetString ( ) ,
2016-09-07 04:57:50 +08:00
true ) ;
// if we did some replacements of reserved characters, and a
// file with the untampered name
// exists, then warn the user that the file as-is shall not be
// loaded
if ( feedback_stream ) {
if ( module_basename ! = original_module_basename & &
orig_script_fspec . Exists ( ) ) {
const char * reason_for_complaint =
was_keyword ? " conflicts with a keyword "
: " contains reserved characters " ;
if ( script_fspec . Exists ( ) )
feedback_stream - > Printf (
" warning: the symbol file '%s' contains a debug "
" script. However, its name "
" '%s' %s and as such cannot be loaded. LLDB will "
" load '%s' instead. Consider removing the file with "
" the malformed name to "
" eliminate this warning. \n " ,
symfile_spec . GetPath ( ) . c_str ( ) ,
original_path_string . GetData ( ) , reason_for_complaint ,
path_string . GetData ( ) ) ;
else
feedback_stream - > Printf (
" warning: the symbol file '%s' contains a debug "
" script. However, its name "
" %s and as such cannot be loaded. If you intend "
" to have this script loaded, please rename '%s' to "
" '%s' and retry. \n " ,
symfile_spec . GetPath ( ) . c_str ( ) , reason_for_complaint ,
original_path_string . GetData ( ) ,
path_string . GetData ( ) ) ;
}
}
if ( script_fspec . Exists ( ) ) {
file_list . Append ( script_fspec ) ;
break ;
2013-01-12 07:44:27 +08:00
}
2016-09-07 04:57:50 +08:00
// If we didn't find the python file, then keep
// stripping the extensions and try again
ConstString filename_no_extension (
module_spec . GetFileNameStrippingExtension ( ) ) ;
if ( module_spec . GetFilename ( ) = = filename_no_extension )
break ;
module_spec . GetFilename ( ) = filename_no_extension ;
}
2013-01-12 07:44:27 +08:00
}
2016-09-07 04:57:50 +08:00
}
2012-11-08 10:44:10 +08:00
}
2016-09-07 04:57:50 +08:00
}
2012-11-08 10:44:10 +08:00
}
2016-09-07 04:57:50 +08:00
}
return file_list ;
2012-11-08 10:22:02 +08:00
}
2011-03-24 12:28:38 +08:00
2017-05-12 12:51:55 +08:00
Status PlatformDarwin : : ResolveSymbolFile ( Target & target ,
const ModuleSpec & sym_spec ,
FileSpec & sym_file ) {
Status error ;
2016-09-07 04:57:50 +08:00
sym_file = sym_spec . GetSymbolFileSpec ( ) ;
2017-03-09 01:56:08 +08:00
llvm : : sys : : fs : : file_status st ;
if ( status ( sym_file . GetPath ( ) , st , false ) ) {
error . SetErrorString ( " Could not stat file! " ) ;
return error ;
}
if ( exists ( st ) ) {
if ( is_directory ( st ) ) {
2016-09-07 04:57:50 +08:00
sym_file = Symbols : : FindSymbolFileInBundle (
sym_file , sym_spec . GetUUIDPtr ( ) , sym_spec . GetArchitecturePtr ( ) ) ;
2012-09-12 10:03:59 +08:00
}
2016-09-07 04:57:50 +08:00
} else {
if ( sym_spec . GetUUID ( ) . IsValid ( ) ) {
2012-09-12 10:03:59 +08:00
}
2016-09-07 04:57:50 +08:00
}
return error ;
2012-09-12 10:03:59 +08:00
}
2017-05-12 12:51:55 +08:00
static lldb_private : : Status
2016-09-07 04:57:50 +08:00
MakeCacheFolderForFile ( const FileSpec & module_cache_spec ) {
FileSpec module_cache_folder =
module_cache_spec . CopyByRemovingLastPathComponent ( ) ;
2017-03-19 13:48:47 +08:00
return llvm : : sys : : fs : : create_directory ( module_cache_folder . GetPath ( ) ) ;
2013-08-27 07:57:52 +08:00
}
2017-05-12 12:51:55 +08:00
static lldb_private : : Status
2016-09-07 04:57:50 +08:00
BringInRemoteFile ( Platform * platform ,
const lldb_private : : ModuleSpec & module_spec ,
const FileSpec & module_cache_spec ) {
MakeCacheFolderForFile ( module_cache_spec ) ;
2017-05-12 12:51:55 +08:00
Status err = platform - > GetFile ( module_spec . GetFileSpec ( ) , module_cache_spec ) ;
2016-09-07 04:57:50 +08:00
return err ;
2013-08-27 07:57:52 +08:00
}
2017-05-12 12:51:55 +08:00
lldb_private : : Status PlatformDarwin : : GetSharedModuleWithLocalCache (
2016-09-07 04:57:50 +08:00
const lldb_private : : ModuleSpec & module_spec , lldb : : ModuleSP & module_sp ,
const lldb_private : : FileSpecList * module_search_paths_ptr ,
lldb : : ModuleSP * old_module_sp_ptr , bool * did_create_ptr ) {
Log * log ( GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_PLATFORM ) ) ;
if ( log )
log - > Printf ( " [%s] Trying to find module %s/%s - platform path %s/%s symbol "
" path %s/%s " ,
( IsHost ( ) ? " host " : " remote " ) ,
module_spec . GetFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ,
module_spec . GetPlatformFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetPlatformFileSpec ( ) . GetFilename ( ) . AsCString ( ) ,
module_spec . GetSymbolFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetSymbolFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
2017-05-12 12:51:55 +08:00
Status err ;
2016-09-07 04:57:50 +08:00
err = ModuleList : : GetSharedModule ( module_spec , module_sp ,
module_search_paths_ptr , old_module_sp_ptr ,
did_create_ptr ) ;
if ( module_sp )
return err ;
if ( ! IsHost ( ) ) {
std : : string cache_path ( GetLocalCacheDirectory ( ) ) ;
// Only search for a locally cached file if we have a valid cache path
if ( ! cache_path . empty ( ) ) {
std : : string module_path ( module_spec . GetFileSpec ( ) . GetPath ( ) ) ;
cache_path . append ( module_path ) ;
2016-11-03 04:34:10 +08:00
FileSpec module_cache_spec ( cache_path , false ) ;
2016-09-07 04:57:50 +08:00
// if rsync is supported, always bring in the file - rsync will be very
// efficient
// when files are the same on the local and remote end of the connection
if ( this - > GetSupportsRSync ( ) ) {
err = BringInRemoteFile ( this , module_spec , module_cache_spec ) ;
if ( err . Fail ( ) )
return err ;
if ( module_cache_spec . Exists ( ) ) {
Log * log ( GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_PLATFORM ) ) ;
if ( log )
log - > Printf ( " [%s] module %s/%s was rsynced and is now there " ,
( IsHost ( ) ? " host " : " remote " ) ,
module_spec . GetFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
ModuleSpec local_spec ( module_cache_spec ,
module_spec . GetArchitecture ( ) ) ;
module_sp . reset ( new Module ( local_spec ) ) ;
module_sp - > SetPlatformFileSpec ( module_spec . GetFileSpec ( ) ) ;
2017-05-12 12:51:55 +08:00
return Status ( ) ;
2016-09-07 04:57:50 +08:00
}
}
// try to find the module in the cache
if ( module_cache_spec . Exists ( ) ) {
// get the local and remote MD5 and compare
if ( m_remote_platform_sp ) {
// when going over the *slow* GDB remote transfer mechanism we first
2017-03-21 07:54:54 +08:00
// check the hashes of the files - and only do the actual transfer if
// they differ
2016-09-07 04:57:50 +08:00
uint64_t high_local , high_remote , low_local , low_remote ;
2017-03-21 07:54:54 +08:00
auto MD5 = llvm : : sys : : fs : : md5_contents ( module_cache_spec . GetPath ( ) ) ;
if ( ! MD5 )
2017-05-12 12:51:55 +08:00
return Status ( MD5 . getError ( ) ) ;
2017-03-21 07:54:54 +08:00
std : : tie ( high_local , low_local ) = MD5 - > words ( ) ;
2016-09-07 04:57:50 +08:00
m_remote_platform_sp - > CalculateMD5 ( module_spec . GetFileSpec ( ) ,
low_remote , high_remote ) ;
if ( low_local ! = low_remote | | high_local ! = high_remote ) {
// bring in the remote file
Log * log ( GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_PLATFORM ) ) ;
2014-03-04 03:15:20 +08:00
if ( log )
2016-09-07 04:57:50 +08:00
log - > Printf (
" [%s] module %s/%s needs to be replaced from remote copy " ,
( IsHost ( ) ? " host " : " remote " ) ,
module_spec . GetFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
2017-05-12 12:51:55 +08:00
Status err =
BringInRemoteFile ( this , module_spec , module_cache_spec ) ;
2014-03-05 05:20:23 +08:00
if ( err . Fail ( ) )
2016-09-07 04:57:50 +08:00
return err ;
}
2014-03-04 10:07:24 +08:00
}
2016-09-07 04:57:50 +08:00
ModuleSpec local_spec ( module_cache_spec , module_spec . GetArchitecture ( ) ) ;
module_sp . reset ( new Module ( local_spec ) ) ;
module_sp - > SetPlatformFileSpec ( module_spec . GetFileSpec ( ) ) ;
Log * log ( GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_PLATFORM ) ) ;
if ( log )
log - > Printf ( " [%s] module %s/%s was found in the cache " ,
( IsHost ( ) ? " host " : " remote " ) ,
module_spec . GetFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
2017-05-12 12:51:55 +08:00
return Status ( ) ;
2016-09-07 04:57:50 +08:00
}
// bring in the remote module file
if ( log )
log - > Printf ( " [%s] module %s/%s needs to come in remotely " ,
( IsHost ( ) ? " host " : " remote " ) ,
module_spec . GetFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
2017-05-12 12:51:55 +08:00
Status err = BringInRemoteFile ( this , module_spec , module_cache_spec ) ;
2016-09-07 04:57:50 +08:00
if ( err . Fail ( ) )
return err ;
if ( module_cache_spec . Exists ( ) ) {
Log * log ( GetLogIfAnyCategoriesSet ( LIBLLDB_LOG_PLATFORM ) ) ;
if ( log )
log - > Printf ( " [%s] module %s/%s is now cached and fine " ,
( IsHost ( ) ? " host " : " remote " ) ,
module_spec . GetFileSpec ( ) . GetDirectory ( ) . AsCString ( ) ,
module_spec . GetFileSpec ( ) . GetFilename ( ) . AsCString ( ) ) ;
ModuleSpec local_spec ( module_cache_spec , module_spec . GetArchitecture ( ) ) ;
module_sp . reset ( new Module ( local_spec ) ) ;
module_sp - > SetPlatformFileSpec ( module_spec . GetFileSpec ( ) ) ;
2017-05-12 12:51:55 +08:00
return Status ( ) ;
2016-09-07 04:57:50 +08:00
} else
2017-05-12 12:51:55 +08:00
return Status ( " unable to obtain valid module file " ) ;
2016-09-07 04:57:50 +08:00
} else
2017-05-12 12:51:55 +08:00
return Status ( " no cache path " ) ;
2016-09-07 04:57:50 +08:00
} else
2017-05-12 12:51:55 +08:00
return Status ( " unable to resolve module " ) ;
2013-08-27 07:57:52 +08:00
}
2012-02-14 07:10:39 +08:00
2017-05-12 12:51:55 +08:00
Status PlatformDarwin : : GetSharedModule (
2016-09-07 04:57:50 +08:00
const ModuleSpec & module_spec , Process * process , ModuleSP & module_sp ,
const FileSpecList * module_search_paths_ptr , ModuleSP * old_module_sp_ptr ,
bool * did_create_ptr ) {
2017-05-12 12:51:55 +08:00
Status error ;
2016-09-07 04:57:50 +08:00
module_sp . reset ( ) ;
if ( IsRemote ( ) ) {
// If we have a remote platform always, let it try and locate
// the shared module first.
if ( m_remote_platform_sp ) {
error = m_remote_platform_sp - > GetSharedModule (
module_spec , process , module_sp , module_search_paths_ptr ,
old_module_sp_ptr , did_create_ptr ) ;
2012-02-14 07:10:39 +08:00
}
2016-09-07 04:57:50 +08:00
}
if ( ! module_sp ) {
// Fall back to the local platform and find the file locally
error = Platform : : GetSharedModule ( module_spec , process , module_sp ,
module_search_paths_ptr ,
old_module_sp_ptr , did_create_ptr ) ;
const FileSpec & platform_file = module_spec . GetFileSpec ( ) ;
if ( ! module_sp & & module_search_paths_ptr & & platform_file ) {
// We can try to pull off part of the file path up to the bundle
// directory level and try any module search paths...
FileSpec bundle_directory ;
if ( Host : : GetBundleDirectory ( platform_file , bundle_directory ) ) {
if ( platform_file = = bundle_directory ) {
ModuleSpec new_module_spec ( module_spec ) ;
new_module_spec . GetFileSpec ( ) = bundle_directory ;
if ( Host : : ResolveExecutableInBundle ( new_module_spec . GetFileSpec ( ) ) ) {
2017-05-12 12:51:55 +08:00
Status new_error ( Platform : : GetSharedModule (
2016-09-07 04:57:50 +08:00
new_module_spec , process , module_sp , NULL , old_module_sp_ptr ,
did_create_ptr ) ) ;
if ( module_sp )
return new_error ;
}
} else {
char platform_path [ PATH_MAX ] ;
char bundle_dir [ PATH_MAX ] ;
platform_file . GetPath ( platform_path , sizeof ( platform_path ) ) ;
const size_t bundle_directory_len =
bundle_directory . GetPath ( bundle_dir , sizeof ( bundle_dir ) ) ;
char new_path [ PATH_MAX ] ;
size_t num_module_search_paths = module_search_paths_ptr - > GetSize ( ) ;
for ( size_t i = 0 ; i < num_module_search_paths ; + + i ) {
const size_t search_path_len =
module_search_paths_ptr - > GetFileSpecAtIndex ( i ) . GetPath (
new_path , sizeof ( new_path ) ) ;
if ( search_path_len < sizeof ( new_path ) ) {
snprintf ( new_path + search_path_len ,
sizeof ( new_path ) - search_path_len , " /%s " ,
platform_path + bundle_directory_len ) ;
FileSpec new_file_spec ( new_path , false ) ;
if ( new_file_spec . Exists ( ) ) {
ModuleSpec new_module_spec ( module_spec ) ;
new_module_spec . GetFileSpec ( ) = new_file_spec ;
2017-05-12 12:51:55 +08:00
Status new_error ( Platform : : GetSharedModule (
2016-09-07 04:57:50 +08:00
new_module_spec , process , module_sp , NULL ,
old_module_sp_ptr , did_create_ptr ) ) ;
if ( module_sp ) {
module_sp - > SetPlatformFileSpec ( new_file_spec ) ;
return new_error ;
2012-02-14 07:10:39 +08:00
}
2016-09-07 04:57:50 +08:00
}
2012-02-14 07:10:39 +08:00
}
2016-09-07 04:57:50 +08:00
}
2012-02-14 07:10:39 +08:00
}
2016-09-07 04:57:50 +08:00
}
2012-02-14 07:10:39 +08:00
}
2016-09-07 04:57:50 +08:00
}
if ( module_sp )
module_sp - > SetPlatformFileSpec ( module_spec . GetFileSpec ( ) ) ;
return error ;
2012-02-14 07:10:39 +08:00
}
2011-03-24 12:28:38 +08:00
size_t
2016-09-07 04:57:50 +08:00
PlatformDarwin : : GetSoftwareBreakpointTrapOpcode ( Target & target ,
BreakpointSite * bp_site ) {
const uint8_t * trap_opcode = nullptr ;
uint32_t trap_opcode_size = 0 ;
bool bp_is_thumb = false ;
llvm : : Triple : : ArchType machine = target . GetArchitecture ( ) . GetMachine ( ) ;
switch ( machine ) {
case llvm : : Triple : : aarch64 : {
// TODO: fix this with actual darwin breakpoint opcode for arm64.
// right now debugging uses the Z packets with GDB remote so this
// is not needed, but the size needs to be correct...
static const uint8_t g_arm64_breakpoint_opcode [ ] = { 0xFE , 0xDE , 0xFF , 0xE7 } ;
trap_opcode = g_arm64_breakpoint_opcode ;
trap_opcode_size = sizeof ( g_arm64_breakpoint_opcode ) ;
} break ;
case llvm : : Triple : : thumb :
bp_is_thumb = true ;
LLVM_FALLTHROUGH ;
case llvm : : Triple : : arm : {
static const uint8_t g_arm_breakpoint_opcode [ ] = { 0xFE , 0xDE , 0xFF , 0xE7 } ;
static const uint8_t g_thumb_breakpooint_opcode [ ] = { 0xFE , 0xDE } ;
// Auto detect arm/thumb if it wasn't explicitly specified
if ( ! bp_is_thumb ) {
lldb : : BreakpointLocationSP bp_loc_sp ( bp_site - > GetOwnerAtIndex ( 0 ) ) ;
if ( bp_loc_sp )
bp_is_thumb = bp_loc_sp - > GetAddress ( ) . GetAddressClass ( ) = =
eAddressClassCodeAlternateISA ;
2011-03-24 12:28:38 +08:00
}
2016-09-07 04:57:50 +08:00
if ( bp_is_thumb ) {
trap_opcode = g_thumb_breakpooint_opcode ;
trap_opcode_size = sizeof ( g_thumb_breakpooint_opcode ) ;
break ;
2011-03-24 12:28:38 +08:00
}
2016-09-07 04:57:50 +08:00
trap_opcode = g_arm_breakpoint_opcode ;
trap_opcode_size = sizeof ( g_arm_breakpoint_opcode ) ;
} break ;
case llvm : : Triple : : ppc :
case llvm : : Triple : : ppc64 : {
static const uint8_t g_ppc_breakpoint_opcode [ ] = { 0x7F , 0xC0 , 0x00 , 0x08 } ;
trap_opcode = g_ppc_breakpoint_opcode ;
trap_opcode_size = sizeof ( g_ppc_breakpoint_opcode ) ;
} break ;
default :
return Platform : : GetSoftwareBreakpointTrapOpcode ( target , bp_site ) ;
}
if ( trap_opcode & & trap_opcode_size ) {
if ( bp_site - > SetTrapOpcode ( trap_opcode , trap_opcode_size ) )
return trap_opcode_size ;
}
return 0 ;
2011-03-24 12:28:38 +08:00
}
2016-09-07 04:57:50 +08:00
bool PlatformDarwin : : ModuleIsExcludedForUnconstrainedSearches (
lldb_private : : Target & target , const lldb : : ModuleSP & module_sp ) {
if ( ! module_sp )
return false ;
ObjectFile * obj_file = module_sp - > GetObjectFile ( ) ;
if ( ! obj_file )
return false ;
ObjectFile : : Type obj_type = obj_file - > GetType ( ) ;
if ( obj_type = = ObjectFile : : eTypeDynamicLinker )
return true ;
else
return false ;
2011-10-29 07:14:11 +08:00
}
2011-12-09 15:50:50 +08:00
2016-09-07 04:57:50 +08:00
bool PlatformDarwin : : x86GetSupportedArchitectureAtIndex ( uint32_t idx ,
ArchSpec & arch ) {
ArchSpec host_arch = HostInfo : : GetArchitecture ( HostInfo : : eArchKindDefault ) ;
if ( host_arch . GetCore ( ) = = ArchSpec : : eCore_x86_64_x86_64h ) {
switch ( idx ) {
case 0 :
arch = host_arch ;
return true ;
case 1 :
arch . SetTriple ( " x86_64-apple-macosx " ) ;
return true ;
case 2 :
arch = HostInfo : : GetArchitecture ( HostInfo : : eArchKind32 ) ;
return true ;
default :
return false ;
2012-02-25 14:56:35 +08:00
}
2016-09-07 04:57:50 +08:00
} else {
if ( idx = = 0 ) {
arch = HostInfo : : GetArchitecture ( HostInfo : : eArchKindDefault ) ;
return arch . IsValid ( ) ;
} else if ( idx = = 1 ) {
ArchSpec platform_arch (
HostInfo : : GetArchitecture ( HostInfo : : eArchKindDefault ) ) ;
ArchSpec platform_arch64 (
HostInfo : : GetArchitecture ( HostInfo : : eArchKind64 ) ) ;
if ( platform_arch . IsExactMatch ( platform_arch64 ) ) {
// This macosx platform supports both 32 and 64 bit. Since we already
// returned the 64 bit arch for idx == 0, return the 32 bit arch
// for idx == 1
arch = HostInfo : : GetArchitecture ( HostInfo : : eArchKind32 ) ;
return arch . IsValid ( ) ;
}
2012-02-25 14:56:35 +08:00
}
2016-09-07 04:57:50 +08:00
}
return false ;
2012-02-25 14:56:35 +08:00
}
2011-12-09 15:50:50 +08:00
// The architecture selection rules for arm processors
2016-09-07 04:57:50 +08:00
// These cpu subtypes have distinct names (e.g. armv7f) but armv7 binaries run
// fine on an armv7f processor.
2011-12-09 15:50:50 +08:00
2016-09-07 04:57:50 +08:00
bool PlatformDarwin : : ARMGetSupportedArchitectureAtIndex ( uint32_t idx ,
ArchSpec & arch ) {
ArchSpec system_arch ( GetSystemArchitecture ( ) ) ;
2014-03-30 02:54:20 +08:00
2016-09-07 04:57:50 +08:00
// When lldb is running on a watch or tv, set the arch OS name appropriately.
# if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
2015-11-21 12:00:43 +08:00
# define OSNAME "tvos"
2016-09-07 04:57:50 +08:00
# elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
2015-11-21 12:00:43 +08:00
# define OSNAME "watchos"
2017-04-18 06:52:20 +08:00
# elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
# define OSNAME "bridgeos"
2015-11-21 12:00:43 +08:00
# else
# define OSNAME "ios"
# endif
2016-09-07 04:57:50 +08:00
const ArchSpec : : Core system_core = system_arch . GetCore ( ) ;
switch ( system_core ) {
default :
switch ( idx ) {
case 0 :
arch . SetTriple ( " arm64-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv7f-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv7k-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv7s-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " armv7m-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " armv7em-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 12 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 13 :
arch . SetTriple ( " thumbv7f-apple- " OSNAME ) ;
return true ;
case 14 :
arch . SetTriple ( " thumbv7k-apple- " OSNAME ) ;
return true ;
case 15 :
arch . SetTriple ( " thumbv7s-apple- " OSNAME ) ;
return true ;
case 16 :
arch . SetTriple ( " thumbv7m-apple- " OSNAME ) ;
return true ;
case 17 :
arch . SetTriple ( " thumbv7em-apple- " OSNAME ) ;
return true ;
case 18 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 19 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 20 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 21 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 22 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
2011-12-09 15:50:50 +08:00
default :
2016-09-07 04:57:50 +08:00
break ;
2011-12-09 15:50:50 +08:00
}
2016-09-07 04:57:50 +08:00
break ;
case ArchSpec : : eCore_arm_arm64 :
switch ( idx ) {
case 0 :
arch . SetTriple ( " arm64-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv7s-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv7f-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv7m-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv7em-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 12 :
arch . SetTriple ( " thumbv7f-apple- " OSNAME ) ;
return true ;
case 13 :
arch . SetTriple ( " thumbv7k-apple- " OSNAME ) ;
return true ;
case 14 :
arch . SetTriple ( " thumbv7s-apple- " OSNAME ) ;
return true ;
case 15 :
arch . SetTriple ( " thumbv7m-apple- " OSNAME ) ;
return true ;
case 16 :
arch . SetTriple ( " thumbv7em-apple- " OSNAME ) ;
return true ;
case 17 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 18 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 19 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 20 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 21 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv7f :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv7f-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumbv7f-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 12 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 13 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv7k :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv7k-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumbv7k-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 12 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 13 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv7s :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv7s-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumbv7s-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 12 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 13 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv7m :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv7m-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumbv7m-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 12 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 13 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv7em :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv7em-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumbv7em-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 12 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 13 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv7 :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv7-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " thumbv7-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 10 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 11 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv6m :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv6m-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " thumbv6m-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 8 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 9 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv6 :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv6-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " thumbv6-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 6 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 7 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv5 :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv5-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " thumbv5-apple- " OSNAME ) ;
return true ;
case 4 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 5 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
case ArchSpec : : eCore_arm_armv4 :
switch ( idx ) {
case 0 :
arch . SetTriple ( " armv4-apple- " OSNAME ) ;
return true ;
case 1 :
arch . SetTriple ( " arm-apple- " OSNAME ) ;
return true ;
case 2 :
arch . SetTriple ( " thumbv4t-apple- " OSNAME ) ;
return true ;
case 3 :
arch . SetTriple ( " thumb-apple- " OSNAME ) ;
return true ;
default :
break ;
}
break ;
}
arch . Clear ( ) ;
return false ;
2011-12-09 15:50:50 +08:00
}
2012-02-25 14:56:35 +08:00
2017-12-09 11:06:19 +08:00
// Return a directory path like /Applications/Xcode.app/Contents/Developer
2016-09-07 04:57:50 +08:00
const char * PlatformDarwin : : GetDeveloperDirectory ( ) {
std : : lock_guard < std : : mutex > guard ( m_mutex ) ;
if ( m_developer_directory . empty ( ) ) {
bool developer_dir_path_valid = false ;
char developer_dir_path [ PATH_MAX ] ;
FileSpec temp_file_spec ;
2017-12-09 11:06:19 +08:00
// Get the lldb framework's file path, and if it exists, truncate some
// components to only the developer directory path.
2016-09-07 04:57:50 +08:00
if ( HostInfo : : GetLLDBPath ( ePathTypeLLDBShlibDir , temp_file_spec ) ) {
if ( temp_file_spec . GetPath ( developer_dir_path ,
sizeof ( developer_dir_path ) ) ) {
2017-12-09 11:06:19 +08:00
// e.g. /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework
2016-09-07 04:57:50 +08:00
char * shared_frameworks =
strstr ( developer_dir_path , " /SharedFrameworks/LLDB.framework " ) ;
if ( shared_frameworks ) {
2017-12-09 11:06:19 +08:00
shared_frameworks [ 0 ] = ' \0 ' ; // truncate developer_dir_path at this point
strncat ( developer_dir_path , " /Developer " , sizeof ( developer_dir_path ) - 1 ) ; // add /Developer on
2016-09-07 04:57:50 +08:00
developer_dir_path_valid = true ;
} else {
2017-12-09 11:06:19 +08:00
// e.g. /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework
char * developer_toolchains =
strstr ( developer_dir_path , " /Contents/Developer/Toolchains/ " ) ;
if ( developer_toolchains ) {
developer_toolchains + = sizeof ( " /Contents/Developer " ) - 1 ;
developer_toolchains [ 0 ] = ' \0 ' ; // truncate developer_dir_path at this point
2016-09-07 04:57:50 +08:00
developer_dir_path_valid = true ;
}
2012-02-25 14:56:35 +08:00
}
2016-09-07 04:57:50 +08:00
}
2012-02-25 14:56:35 +08:00
}
2016-09-07 04:57:50 +08:00
if ( ! developer_dir_path_valid ) {
std : : string xcode_dir_path ;
const char * xcode_select_prefix_dir = getenv ( " XCODE_SELECT_PREFIX_DIR " ) ;
if ( xcode_select_prefix_dir )
xcode_dir_path . append ( xcode_select_prefix_dir ) ;
xcode_dir_path . append ( " /usr/share/xcode-select/xcode_dir_path " ) ;
2016-11-03 04:34:10 +08:00
temp_file_spec . SetFile ( xcode_dir_path , false ) ;
2017-03-07 07:42:14 +08:00
auto dir_buffer =
Make sure DataBufferLLVM contents are writable
Summary:
We sometimes need to write to the object file we've mapped into memory,
generally to apply relocations to debug info sections. We've had that
ability before, but with the introduction of DataBufferLLVM, we have
lost it, as the underlying llvm class (MemoryBuffer) only supports
read-only mappings.
This switches DataBufferLLVM to use the new llvm::WritableMemoryBuffer
class as a back-end, as this one guarantees to return a writable buffer.
This removes the need for the "Private" flag to the DataBufferLLVM
creation functions, as it was really used to mean "writable". The LLVM
function also does not have the NullTerminate flag, so I've modified our
clients to not require this feature and removed that flag as well.
Reviewers: zturner, clayborg, jingham
Subscribers: emaste, aprantl, arichardson, krytarowski, lldb-commits
Differential Revision: https://reviews.llvm.org/D40079
llvm-svn: 321255
2017-12-21 18:54:30 +08:00
DataBufferLLVM : : CreateFromPath ( temp_file_spec . GetPath ( ) ) ;
2017-03-07 07:42:14 +08:00
if ( dir_buffer & & dir_buffer - > GetByteSize ( ) > 0 ) {
llvm : : StringRef path_ref ( dir_buffer - > GetChars ( ) ) ;
// Trim tailing newlines and make sure there is enough room for a null
// terminator.
path_ref =
path_ref . rtrim ( " \r \n " ) . take_front ( sizeof ( developer_dir_path ) - 1 ) ;
: : memcpy ( developer_dir_path , path_ref . data ( ) , path_ref . size ( ) ) ;
developer_dir_path [ path_ref . size ( ) ] = ' \0 ' ;
2016-09-07 04:57:50 +08:00
developer_dir_path_valid = true ;
}
}
2012-05-15 10:33:01 +08:00
2016-09-07 04:57:50 +08:00
if ( ! developer_dir_path_valid ) {
FileSpec xcode_select_cmd ( " /usr/bin/xcode-select " , false ) ;
if ( xcode_select_cmd . Exists ( ) ) {
int exit_status = - 1 ;
int signo = - 1 ;
std : : string command_output ;
2017-05-12 12:51:55 +08:00
Status error =
2016-09-07 04:57:50 +08:00
Host : : RunShellCommand ( " /usr/bin/xcode-select --print-path " ,
NULL , // current working directory
& exit_status , & signo , & command_output ,
2 , // short timeout
false ) ; // don't run in a shell
if ( error . Success ( ) & & exit_status = = 0 & & ! command_output . empty ( ) ) {
const char * cmd_output_ptr = command_output . c_str ( ) ;
developer_dir_path [ sizeof ( developer_dir_path ) - 1 ] = ' \0 ' ;
size_t i ;
for ( i = 0 ; i < sizeof ( developer_dir_path ) - 1 ; i + + ) {
if ( cmd_output_ptr [ i ] = = ' \r ' | | cmd_output_ptr [ i ] = = ' \n ' | |
cmd_output_ptr [ i ] = = ' \0 ' )
break ;
developer_dir_path [ i ] = cmd_output_ptr [ i ] ;
}
developer_dir_path [ i ] = ' \0 ' ;
FileSpec devel_dir ( developer_dir_path , false ) ;
2017-03-09 01:56:08 +08:00
if ( llvm : : sys : : fs : : is_directory ( devel_dir . GetPath ( ) ) ) {
2016-09-07 04:57:50 +08:00
developer_dir_path_valid = true ;
}
}
}
2012-05-15 10:33:01 +08:00
}
2016-09-07 04:57:50 +08:00
if ( developer_dir_path_valid ) {
temp_file_spec . SetFile ( developer_dir_path , false ) ;
if ( temp_file_spec . Exists ( ) ) {
m_developer_directory . assign ( developer_dir_path ) ;
return m_developer_directory . c_str ( ) ;
}
}
// Assign a single NULL character so we know we tried to find the device
// support directory and we don't keep trying to find it over and over.
m_developer_directory . assign ( 1 , ' \0 ' ) ;
}
// We should have put a single NULL character into m_developer_directory
// or it should have a valid path if the code gets here
assert ( m_developer_directory . empty ( ) = = false ) ;
if ( m_developer_directory [ 0 ] )
return m_developer_directory . c_str ( ) ;
return NULL ;
2012-05-15 10:33:01 +08:00
}
2016-09-07 04:57:50 +08:00
BreakpointSP PlatformDarwin : : SetThreadCreationBreakpoint ( Target & target ) {
BreakpointSP bp_sp ;
static const char * g_bp_names [ ] = {
" start_wqthread " , " _pthread_wqthread " , " _pthread_start " ,
} ;
static const char * g_bp_modules [ ] = { " libsystem_c.dylib " ,
" libSystem.B.dylib " } ;
FileSpecList bp_modules ;
for ( size_t i = 0 ; i < llvm : : array_lengthof ( g_bp_modules ) ; i + + ) {
const char * bp_module = g_bp_modules [ i ] ;
bp_modules . Append ( FileSpec ( bp_module , false ) ) ;
}
bool internal = true ;
bool hardware = false ;
LazyBool skip_prologue = eLazyBoolNo ;
bp_sp = target . CreateBreakpoint ( & bp_modules , NULL , g_bp_names ,
llvm : : array_lengthof ( g_bp_names ) ,
eFunctionNameTypeFull , eLanguageTypeUnknown ,
0 , skip_prologue , internal , hardware ) ;
bp_sp - > SetBreakpointKind ( " thread-creation " ) ;
return bp_sp ;
}
2013-09-10 10:09:47 +08:00
int32_t
2016-09-07 04:57:50 +08:00
PlatformDarwin : : GetResumeCountForLaunchInfo ( ProcessLaunchInfo & launch_info ) {
const FileSpec & shell = launch_info . GetShell ( ) ;
if ( ! shell )
return 1 ;
std : : string shell_string = shell . GetPath ( ) ;
const char * shell_name = strrchr ( shell_string . c_str ( ) , ' / ' ) ;
if ( shell_name = = NULL )
shell_name = shell_string . c_str ( ) ;
else
shell_name + + ;
if ( strcmp ( shell_name , " sh " ) = = 0 ) {
// /bin/sh re-exec's itself as /bin/bash requiring another resume.
// But it only does this if the COMMAND_MODE environment variable
// is set to "legacy".
Add Utility/Environment class for handling... environments
Summary:
There was some confusion in the code about how to represent process
environment. Most of the code (ab)used the Args class for this purpose,
but some of it used a more basic StringList class instead. In either
case, the fact that the underlying abstraction did not provide primitive
operations for the typical environment operations meant that even a
simple operation like checking for an environment variable value was
several lines of code.
This patch adds a separate Environment class, which is essentialy a
llvm::StringMap<std::string> in disguise. To standard StringMap
functionality, it adds a couple of new functions, which are specific to
the environment use case:
- (most important) envp conversion for passing into execve() and likes.
Instead of trying to maintain a constantly up-to-date envp view, it
provides a function which creates a envp view on demand, with the
expectation that this will be called as the very last thing before
handing the value to the system function.
- insert(StringRef KeyEqValue) - splits KeyEqValue into (key, value)
pair and inserts it into the environment map.
- compose(value_type KeyValue) - takes a map entry and converts in back
into "KEY=VALUE" representation.
With this interface most of the environment-manipulating code becomes
one-liners. The only tricky part was maintaining compatibility in
SBLaunchInfo, which expects that the environment entries are accessible
by index and that the returned const char* is backed by the launch info
object (random access into maps is hard and the map stores the entry in
a deconstructed form, so we cannot just return a .c_str() value). To
solve this, I have the SBLaunchInfo convert the environment into the
"envp" form, and use it to answer the environment queries. Extra code is
added to make sure the envp version is always in sync.
(This also improves the layering situation as Args was in the Interpreter module
whereas Environment is in Utility.)
Reviewers: zturner, davide, jingham, clayborg
Subscribers: emaste, lldb-commits, mgorny
Differential Revision: https://reviews.llvm.org/D41359
llvm-svn: 322174
2018-01-10 19:57:31 +08:00
if ( launch_info . GetEnvironment ( ) . lookup ( " COMMAND_MODE " ) = = " legacy " )
return 2 ;
2016-09-07 04:57:50 +08:00
return 1 ;
} else if ( strcmp ( shell_name , " csh " ) = = 0 | |
strcmp ( shell_name , " tcsh " ) = = 0 | |
strcmp ( shell_name , " zsh " ) = = 0 ) {
// csh and tcsh always seem to re-exec themselves.
return 2 ;
} else
return 1 ;
2013-09-10 10:09:47 +08:00
}
2014-02-14 07:11:45 +08:00
2016-09-07 04:57:50 +08:00
void PlatformDarwin : : CalculateTrapHandlerSymbolNames ( ) {
m_trap_handlers . push_back ( ConstString ( " _sigtramp " ) ) ;
2014-12-05 09:16:31 +08:00
}
static const char * const sdk_strings [ ] = {
2016-09-07 04:57:50 +08:00
" MacOSX " , " iPhoneSimulator " , " iPhoneOS " ,
2014-12-05 09:16:31 +08:00
} ;
2016-09-07 04:57:50 +08:00
static FileSpec CheckPathForXcode ( const FileSpec & fspec ) {
if ( fspec . Exists ( ) ) {
const char substr [ ] = " .app/Contents/ " ;
std : : string path_to_shlib = fspec . GetPath ( ) ;
size_t pos = path_to_shlib . rfind ( substr ) ;
if ( pos ! = std : : string : : npos ) {
path_to_shlib . erase ( pos + strlen ( substr ) ) ;
2016-11-03 04:34:10 +08:00
FileSpec ret ( path_to_shlib , false ) ;
2016-09-07 04:57:50 +08:00
FileSpec xcode_binary_path = ret ;
xcode_binary_path . AppendPathComponent ( " MacOS " ) ;
xcode_binary_path . AppendPathComponent ( " Xcode " ) ;
if ( xcode_binary_path . Exists ( ) ) {
return ret ;
}
2015-10-20 08:22:50 +08:00
}
2016-09-07 04:57:50 +08:00
}
return FileSpec ( ) ;
2015-10-20 08:22:50 +08:00
}
2016-09-07 04:57:50 +08:00
static FileSpec GetXcodeContentsPath ( ) {
static FileSpec g_xcode_filespec ;
2017-02-07 01:55:02 +08:00
static llvm : : once_flag g_once_flag ;
llvm : : call_once ( g_once_flag , [ ] ( ) {
2016-09-07 04:57:50 +08:00
FileSpec fspec ;
// First get the program file spec. If lldb.so or LLDB.framework is running
// in a program and that program is Xcode, the path returned with be the
// path
// to Xcode.app/Contents/MacOS/Xcode, so this will be the correct Xcode to
// use.
fspec = HostInfo : : GetProgramFileSpec ( ) ;
if ( fspec ) {
// Ignore the current binary if it is python.
std : : string basename_lower = fspec . GetFilename ( ) . GetCString ( ) ;
std : : transform ( basename_lower . begin ( ) , basename_lower . end ( ) ,
basename_lower . begin ( ) , tolower ) ;
if ( basename_lower ! = " python " ) {
g_xcode_filespec = CheckPathForXcode ( fspec ) ;
}
}
2015-10-20 08:22:50 +08:00
2016-09-07 04:57:50 +08:00
// Next check DEVELOPER_DIR environment variable
if ( ! g_xcode_filespec ) {
const char * developer_dir_env_var = getenv ( " DEVELOPER_DIR " ) ;
if ( developer_dir_env_var & & developer_dir_env_var [ 0 ] ) {
g_xcode_filespec =
CheckPathForXcode ( FileSpec ( developer_dir_env_var , true ) ) ;
}
// Fall back to using "xcrun" to find the selected Xcode
if ( ! g_xcode_filespec ) {
int status = 0 ;
int signo = 0 ;
std : : string output ;
const char * command = " /usr/bin/xcode-select -p " ;
2017-05-12 12:51:55 +08:00
lldb_private : : Status error = Host : : RunShellCommand (
2016-09-07 04:57:50 +08:00
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 ) ;
}
output . append ( " /.. " ) ;
2016-11-03 04:34:10 +08:00
g_xcode_filespec = CheckPathForXcode ( FileSpec ( output , false ) ) ;
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
}
}
} ) ;
return g_xcode_filespec ;
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
bool PlatformDarwin : : SDKSupportsModules ( SDKType sdk_type , uint32_t major ,
uint32_t minor , uint32_t micro ) {
switch ( sdk_type ) {
case SDKType : : MacOSX :
if ( major > 10 | | ( major = = 10 & & minor > = 10 ) )
return true ;
break ;
case SDKType : : iPhoneOS :
case SDKType : : iPhoneSimulator :
if ( major > = 8 )
return true ;
break ;
}
return false ;
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
bool PlatformDarwin : : SDKSupportsModules ( SDKType desired_type ,
const FileSpec & sdk_path ) {
ConstString last_path_component = sdk_path . GetLastPathComponent ( ) ;
if ( last_path_component ) {
const llvm : : StringRef sdk_name = last_path_component . GetStringRef ( ) ;
llvm : : StringRef version_part ;
if ( sdk_name . startswith ( sdk_strings [ ( int ) desired_type ] ) ) {
version_part =
sdk_name . drop_front ( strlen ( sdk_strings [ ( int ) desired_type ] ) ) ;
} else {
return false ;
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
const size_t major_dot_offset = version_part . find ( ' . ' ) ;
if ( major_dot_offset = = llvm : : StringRef : : npos )
return false ;
const llvm : : StringRef major_version =
version_part . slice ( 0 , major_dot_offset ) ;
const llvm : : StringRef minor_part =
version_part . drop_front ( major_dot_offset + 1 ) ;
const size_t minor_dot_offset = minor_part . find ( ' . ' ) ;
if ( minor_dot_offset = = llvm : : StringRef : : npos )
return false ;
const llvm : : StringRef minor_version = minor_part . slice ( 0 , minor_dot_offset ) ;
unsigned int major = 0 ;
unsigned int minor = 0 ;
unsigned int micro = 0 ;
if ( major_version . getAsInteger ( 10 , major ) )
return false ;
if ( minor_version . getAsInteger ( 10 , minor ) )
return false ;
return SDKSupportsModules ( desired_type , major , minor , micro ) ;
}
return false ;
2014-12-05 09:16:31 +08:00
}
2017-03-09 01:56:08 +08:00
FileSpec : : EnumerateDirectoryResult PlatformDarwin : : DirectoryEnumerator (
void * baton , llvm : : sys : : fs : : file_type file_type , const FileSpec & spec ) {
2016-09-07 04:57:50 +08:00
SDKEnumeratorInfo * enumerator_info = static_cast < SDKEnumeratorInfo * > ( baton ) ;
if ( SDKSupportsModules ( enumerator_info - > sdk_type , spec ) ) {
enumerator_info - > found_path = spec ;
2014-12-05 09:16:31 +08:00
return FileSpec : : EnumerateDirectoryResult : : eEnumerateDirectoryResultNext ;
2016-09-07 04:57:50 +08:00
}
return FileSpec : : EnumerateDirectoryResult : : eEnumerateDirectoryResultNext ;
2015-05-13 08:25:54 +08:00
}
2014-12-05 09:16:31 +08:00
2016-09-07 04:57:50 +08:00
FileSpec PlatformDarwin : : FindSDKInXcodeForModules ( SDKType sdk_type ,
const FileSpec & sdks_spec ) {
// Look inside Xcode for the required installed iOS SDK version
2017-03-09 01:56:08 +08:00
if ( ! llvm : : sys : : fs : : is_directory ( sdks_spec . GetPath ( ) ) ) {
2016-09-07 04:57:50 +08:00
return FileSpec ( ) ;
2017-03-09 01:56:08 +08:00
}
2016-09-07 04:57:50 +08:00
const bool find_directories = true ;
const bool find_files = false ;
const bool find_other = true ; // include symlinks
SDKEnumeratorInfo enumerator_info ;
enumerator_info . sdk_type = sdk_type ;
2016-11-03 04:34:10 +08:00
FileSpec : : EnumerateDirectory ( sdks_spec . GetPath ( ) , find_directories ,
2016-09-07 04:57:50 +08:00
find_files , find_other , DirectoryEnumerator ,
& enumerator_info ) ;
2017-03-09 01:56:08 +08:00
if ( llvm : : sys : : fs : : is_directory ( enumerator_info . found_path . GetPath ( ) ) )
2016-09-07 04:57:50 +08:00
return enumerator_info . found_path ;
else
return FileSpec ( ) ;
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
FileSpec PlatformDarwin : : GetSDKDirectoryForModules ( SDKType sdk_type ) {
switch ( sdk_type ) {
case SDKType : : MacOSX :
case SDKType : : iPhoneSimulator :
case SDKType : : iPhoneOS :
break ;
}
FileSpec sdks_spec = GetXcodeContentsPath ( ) ;
sdks_spec . AppendPathComponent ( " Developer " ) ;
sdks_spec . AppendPathComponent ( " Platforms " ) ;
switch ( sdk_type ) {
case SDKType : : MacOSX :
sdks_spec . AppendPathComponent ( " MacOSX.platform " ) ;
break ;
case SDKType : : iPhoneSimulator :
sdks_spec . AppendPathComponent ( " iPhoneSimulator.platform " ) ;
break ;
case SDKType : : iPhoneOS :
sdks_spec . AppendPathComponent ( " iPhoneOS.platform " ) ;
break ;
}
sdks_spec . AppendPathComponent ( " Developer " ) ;
sdks_spec . AppendPathComponent ( " SDKs " ) ;
if ( sdk_type = = SDKType : : MacOSX ) {
uint32_t major = 0 ;
uint32_t minor = 0 ;
uint32_t micro = 0 ;
if ( HostInfo : : GetOSVersion ( major , minor , micro ) ) {
if ( SDKSupportsModules ( SDKType : : MacOSX , major , minor , micro ) ) {
// We slightly prefer the exact SDK for this machine. See if it is
// there.
FileSpec native_sdk_spec = sdks_spec ;
StreamString native_sdk_name ;
native_sdk_name . Printf ( " MacOSX%u.%u.sdk " , major , minor ) ;
2016-11-03 04:34:10 +08:00
native_sdk_spec . AppendPathComponent ( native_sdk_name . GetString ( ) ) ;
2016-09-07 04:57:50 +08:00
if ( native_sdk_spec . Exists ( ) ) {
return native_sdk_spec ;
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
}
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
}
return FindSDKInXcodeForModules ( sdk_type , sdks_spec ) ;
2014-12-05 09:16:31 +08:00
}
2016-09-17 10:00:02 +08:00
std : : tuple < uint32_t , uint32_t , uint32_t , llvm : : StringRef >
PlatformDarwin : : ParseVersionBuildDir ( llvm : : StringRef dir ) {
uint32_t major , minor , update ;
llvm : : StringRef build ;
llvm : : StringRef version_str ;
llvm : : StringRef build_str ;
std : : tie ( version_str , build_str ) = dir . split ( ' ' ) ;
if ( Args : : StringToVersion ( version_str , major , minor , update ) | |
build_str . empty ( ) ) {
if ( build_str . consume_front ( " ( " ) ) {
size_t pos = build_str . find ( ' ) ' ) ;
build = build_str . slice ( 0 , pos ) ;
}
}
return std : : make_tuple ( major , minor , update , build ) ;
}
2016-09-07 04:57:50 +08:00
void PlatformDarwin : : AddClangModuleCompilationOptionsForSDKType (
Target * target , std : : vector < std : : string > & options , SDKType sdk_type ) {
const std : : vector < std : : string > apple_arguments = {
" -x " , " objective-c++ " , " -fobjc-arc " ,
" -fblocks " , " -D_ISO646_H " , " -D__ISO646_H " } ;
options . insert ( options . end ( ) , apple_arguments . begin ( ) , apple_arguments . end ( ) ) ;
StreamString minimum_version_option ;
uint32_t versions [ 3 ] = { 0 , 0 , 0 } ;
bool use_current_os_version = false ;
switch ( sdk_type ) {
case SDKType : : iPhoneOS :
# if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
use_current_os_version = true ;
2015-01-23 02:25:49 +08:00
# else
2016-09-07 04:57:50 +08:00
use_current_os_version = false ;
2015-01-23 02:25:49 +08:00
# endif
2016-09-07 04:57:50 +08:00
break ;
2015-01-23 02:25:49 +08:00
2016-09-07 04:57:50 +08:00
case SDKType : : iPhoneSimulator :
use_current_os_version = false ;
break ;
2015-01-23 02:25:49 +08:00
2016-09-07 04:57:50 +08:00
case SDKType : : MacOSX :
# if defined(__i386__) || defined(__x86_64__)
use_current_os_version = true ;
2015-01-23 02:25:49 +08:00
# else
2016-09-07 04:57:50 +08:00
use_current_os_version = false ;
2015-01-23 02:25:49 +08:00
# endif
2016-09-07 04:57:50 +08:00
break ;
}
bool versions_valid = false ;
if ( use_current_os_version )
versions_valid = GetOSVersion ( versions [ 0 ] , versions [ 1 ] , versions [ 2 ] ) ;
else if ( target ) {
// Our OS doesn't match our executable so we need to get the min OS version
// from the object file
ModuleSP exe_module_sp = target - > GetExecutableModule ( ) ;
if ( exe_module_sp ) {
ObjectFile * object_file = exe_module_sp - > GetObjectFile ( ) ;
if ( object_file )
versions_valid = object_file - > GetMinimumOSVersion ( versions , 3 ) > 0 ;
2014-12-05 09:16:31 +08:00
}
2016-09-07 04:57:50 +08:00
}
// Only add the version-min options if we got a version from somewhere
if ( versions_valid & & versions [ 0 ] ! = UINT32_MAX ) {
// Make any invalid versions be zero if needed
if ( versions [ 1 ] = = UINT32_MAX )
versions [ 1 ] = 0 ;
if ( versions [ 2 ] = = UINT32_MAX )
versions [ 2 ] = 0 ;
switch ( sdk_type ) {
case SDKType : : iPhoneOS :
minimum_version_option . PutCString ( " -mios-version-min= " ) ;
minimum_version_option . PutCString (
clang : : VersionTuple ( versions [ 0 ] , versions [ 1 ] , versions [ 2 ] )
2016-11-03 04:34:10 +08:00
. getAsString ( ) ) ;
2016-09-07 04:57:50 +08:00
break ;
case SDKType : : iPhoneSimulator :
minimum_version_option . PutCString ( " -mios-simulator-version-min= " ) ;
minimum_version_option . PutCString (
clang : : VersionTuple ( versions [ 0 ] , versions [ 1 ] , versions [ 2 ] )
2016-11-03 04:34:10 +08:00
. getAsString ( ) ) ;
2016-09-07 04:57:50 +08:00
break ;
case SDKType : : MacOSX :
minimum_version_option . PutCString ( " -mmacosx-version-min= " ) ;
minimum_version_option . PutCString (
clang : : VersionTuple ( versions [ 0 ] , versions [ 1 ] , versions [ 2 ] )
2016-11-03 04:34:10 +08:00
. getAsString ( ) ) ;
2015-01-23 02:25:49 +08:00
}
2016-09-07 04:57:50 +08:00
options . push_back ( minimum_version_option . GetString ( ) ) ;
}
2015-01-23 02:25:49 +08:00
2016-09-07 04:57:50 +08:00
FileSpec sysroot_spec ;
// Scope for mutex locker below
{
std : : lock_guard < std : : mutex > guard ( m_mutex ) ;
sysroot_spec = GetSDKDirectoryForModules ( sdk_type ) ;
}
2016-05-18 09:59:10 +08:00
2017-03-09 01:56:08 +08:00
if ( llvm : : sys : : fs : : is_directory ( sysroot_spec . GetPath ( ) ) ) {
2016-09-07 04:57:50 +08:00
options . push_back ( " -isysroot " ) ;
options . push_back ( sysroot_spec . GetPath ( ) ) ;
}
2014-12-05 09:16:31 +08:00
}
2015-08-27 08:53:57 +08:00
2016-09-07 04:57:50 +08:00
ConstString PlatformDarwin : : GetFullNameForDylib ( ConstString basename ) {
if ( basename . IsEmpty ( ) )
return basename ;
2015-08-27 08:53:57 +08:00
2016-09-07 04:57:50 +08:00
StreamString stream ;
stream . Printf ( " lib%s.dylib " , basename . GetCString ( ) ) ;
2016-11-17 05:15:24 +08:00
return ConstString ( stream . GetString ( ) ) ;
2016-09-07 04:57:50 +08:00
}
2015-11-06 06:33:17 +08:00
2016-09-07 04:57:50 +08:00
bool PlatformDarwin : : GetOSVersion ( uint32_t & major , uint32_t & minor ,
uint32_t & update , Process * process ) {
if ( process & & strstr ( GetPluginName ( ) . GetCString ( ) , " -simulator " ) ) {
lldb_private : : ProcessInstanceInfo proc_info ;
if ( Host : : GetProcessInfo ( process - > GetID ( ) , proc_info ) ) {
Add Utility/Environment class for handling... environments
Summary:
There was some confusion in the code about how to represent process
environment. Most of the code (ab)used the Args class for this purpose,
but some of it used a more basic StringList class instead. In either
case, the fact that the underlying abstraction did not provide primitive
operations for the typical environment operations meant that even a
simple operation like checking for an environment variable value was
several lines of code.
This patch adds a separate Environment class, which is essentialy a
llvm::StringMap<std::string> in disguise. To standard StringMap
functionality, it adds a couple of new functions, which are specific to
the environment use case:
- (most important) envp conversion for passing into execve() and likes.
Instead of trying to maintain a constantly up-to-date envp view, it
provides a function which creates a envp view on demand, with the
expectation that this will be called as the very last thing before
handing the value to the system function.
- insert(StringRef KeyEqValue) - splits KeyEqValue into (key, value)
pair and inserts it into the environment map.
- compose(value_type KeyValue) - takes a map entry and converts in back
into "KEY=VALUE" representation.
With this interface most of the environment-manipulating code becomes
one-liners. The only tricky part was maintaining compatibility in
SBLaunchInfo, which expects that the environment entries are accessible
by index and that the returned const char* is backed by the launch info
object (random access into maps is hard and the map stores the entry in
a deconstructed form, so we cannot just return a .c_str() value). To
solve this, I have the SBLaunchInfo convert the environment into the
"envp" form, and use it to answer the environment queries. Extra code is
added to make sure the envp version is always in sync.
(This also improves the layering situation as Args was in the Interpreter module
whereas Environment is in Utility.)
Reviewers: zturner, davide, jingham, clayborg
Subscribers: emaste, lldb-commits, mgorny
Differential Revision: https://reviews.llvm.org/D41359
llvm-svn: 322174
2018-01-10 19:57:31 +08:00
const Environment & env = proc_info . GetEnvironment ( ) ;
if ( Args : : StringToVersion ( env . lookup ( " SIMULATOR_RUNTIME_VERSION " ) , major ,
minor , update ) )
return true ;
2016-09-07 04:57:50 +08:00
Add Utility/Environment class for handling... environments
Summary:
There was some confusion in the code about how to represent process
environment. Most of the code (ab)used the Args class for this purpose,
but some of it used a more basic StringList class instead. In either
case, the fact that the underlying abstraction did not provide primitive
operations for the typical environment operations meant that even a
simple operation like checking for an environment variable value was
several lines of code.
This patch adds a separate Environment class, which is essentialy a
llvm::StringMap<std::string> in disguise. To standard StringMap
functionality, it adds a couple of new functions, which are specific to
the environment use case:
- (most important) envp conversion for passing into execve() and likes.
Instead of trying to maintain a constantly up-to-date envp view, it
provides a function which creates a envp view on demand, with the
expectation that this will be called as the very last thing before
handing the value to the system function.
- insert(StringRef KeyEqValue) - splits KeyEqValue into (key, value)
pair and inserts it into the environment map.
- compose(value_type KeyValue) - takes a map entry and converts in back
into "KEY=VALUE" representation.
With this interface most of the environment-manipulating code becomes
one-liners. The only tricky part was maintaining compatibility in
SBLaunchInfo, which expects that the environment entries are accessible
by index and that the returned const char* is backed by the launch info
object (random access into maps is hard and the map stores the entry in
a deconstructed form, so we cannot just return a .c_str() value). To
solve this, I have the SBLaunchInfo convert the environment into the
"envp" form, and use it to answer the environment queries. Extra code is
added to make sure the envp version is always in sync.
(This also improves the layering situation as Args was in the Interpreter module
whereas Environment is in Utility.)
Reviewers: zturner, davide, jingham, clayborg
Subscribers: emaste, lldb-commits, mgorny
Differential Revision: https://reviews.llvm.org/D41359
llvm-svn: 322174
2018-01-10 19:57:31 +08:00
std : : string dyld_root_path = env . lookup ( " DYLD_ROOT_PATH " ) ;
2016-09-07 04:57:50 +08:00
if ( ! dyld_root_path . empty ( ) ) {
dyld_root_path + = " /System/Library/CoreServices/SystemVersion.plist " ;
ApplePropertyList system_version_plist ( dyld_root_path . c_str ( ) ) ;
std : : string product_version ;
if ( system_version_plist . GetValueAsString ( " ProductVersion " ,
product_version ) ) {
2016-09-17 10:00:02 +08:00
return Args : : StringToVersion ( product_version , major , minor , update ) ;
2015-11-06 06:33:17 +08:00
}
2016-09-07 04:57:50 +08:00
}
2015-11-06 06:33:17 +08:00
}
2016-09-07 04:57:50 +08:00
// For simulator platforms, do NOT call back through
// Platform::GetOSVersion()
// as it might call Process::GetHostOSVersion() which we don't want as it
// will be
// incorrect
return false ;
}
2015-11-06 06:33:17 +08:00
2016-09-07 04:57:50 +08:00
return Platform : : GetOSVersion ( major , minor , update , process ) ;
2015-11-06 06:33:17 +08:00
}
2015-10-20 04:44:01 +08:00
2016-09-07 04:57:50 +08:00
lldb_private : : FileSpec PlatformDarwin : : LocateExecutable ( const char * basename ) {
// A collection of SBFileSpec whose SBFileSpec.m_directory members are filled
// in with
// any executable directories that should be searched.
static std : : vector < FileSpec > g_executable_dirs ;
// Find the global list of directories that we will search for
// executables once so we don't keep doing the work over and over.
2017-02-07 01:55:02 +08:00
static llvm : : once_flag g_once_flag ;
llvm : : call_once ( g_once_flag , [ ] ( ) {
2016-09-07 04:57:50 +08:00
// When locating executables, trust the DEVELOPER_DIR first if it is set
FileSpec xcode_contents_dir = GetXcodeContentsPath ( ) ;
if ( xcode_contents_dir ) {
FileSpec xcode_lldb_resources = xcode_contents_dir ;
xcode_lldb_resources . AppendPathComponent ( " SharedFrameworks " ) ;
xcode_lldb_resources . AppendPathComponent ( " LLDB.framework " ) ;
xcode_lldb_resources . AppendPathComponent ( " Resources " ) ;
if ( xcode_lldb_resources . Exists ( ) ) {
FileSpec dir ;
dir . GetDirectory ( ) . SetCString ( xcode_lldb_resources . GetPath ( ) . c_str ( ) ) ;
g_executable_dirs . push_back ( dir ) ;
}
2015-10-20 04:44:01 +08:00
}
2016-09-07 04:57:50 +08:00
} ) ;
// Now search the global list of executable directories for the executable we
// are looking for
for ( const auto & executable_dir : g_executable_dirs ) {
FileSpec executable_file ;
executable_file . GetDirectory ( ) = executable_dir . GetDirectory ( ) ;
executable_file . GetFilename ( ) . SetCString ( basename ) ;
if ( executable_file . Exists ( ) )
return executable_file ;
}
return FileSpec ( ) ;
2015-10-20 04:44:01 +08:00
}
2016-07-15 05:02:45 +08:00
2017-05-12 12:51:55 +08:00
lldb_private : : Status
2016-09-07 04:57:50 +08:00
PlatformDarwin : : LaunchProcess ( lldb_private : : ProcessLaunchInfo & launch_info ) {
// Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr
// if the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't
// require any specific value; rather, it just needs to exist).
// We will set it here as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag
// is not set. Xcode makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
// LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
// specifically want it unset.
const char * disable_env_var = " IDE_DISABLED_OS_ACTIVITY_DT_MODE " ;
Add Utility/Environment class for handling... environments
Summary:
There was some confusion in the code about how to represent process
environment. Most of the code (ab)used the Args class for this purpose,
but some of it used a more basic StringList class instead. In either
case, the fact that the underlying abstraction did not provide primitive
operations for the typical environment operations meant that even a
simple operation like checking for an environment variable value was
several lines of code.
This patch adds a separate Environment class, which is essentialy a
llvm::StringMap<std::string> in disguise. To standard StringMap
functionality, it adds a couple of new functions, which are specific to
the environment use case:
- (most important) envp conversion for passing into execve() and likes.
Instead of trying to maintain a constantly up-to-date envp view, it
provides a function which creates a envp view on demand, with the
expectation that this will be called as the very last thing before
handing the value to the system function.
- insert(StringRef KeyEqValue) - splits KeyEqValue into (key, value)
pair and inserts it into the environment map.
- compose(value_type KeyValue) - takes a map entry and converts in back
into "KEY=VALUE" representation.
With this interface most of the environment-manipulating code becomes
one-liners. The only tricky part was maintaining compatibility in
SBLaunchInfo, which expects that the environment entries are accessible
by index and that the returned const char* is backed by the launch info
object (random access into maps is hard and the map stores the entry in
a deconstructed form, so we cannot just return a .c_str() value). To
solve this, I have the SBLaunchInfo convert the environment into the
"envp" form, and use it to answer the environment queries. Extra code is
added to make sure the envp version is always in sync.
(This also improves the layering situation as Args was in the Interpreter module
whereas Environment is in Utility.)
Reviewers: zturner, davide, jingham, clayborg
Subscribers: emaste, lldb-commits, mgorny
Differential Revision: https://reviews.llvm.org/D41359
llvm-svn: 322174
2018-01-10 19:57:31 +08:00
auto & env_vars = launch_info . GetEnvironment ( ) ;
if ( ! env_vars . count ( disable_env_var ) ) {
2016-09-07 04:57:50 +08:00
// We want to make sure that OS_ACTIVITY_DT_MODE is set so that
// we get os_log and NSLog messages mirrored to the target process
// stderr.
Add Utility/Environment class for handling... environments
Summary:
There was some confusion in the code about how to represent process
environment. Most of the code (ab)used the Args class for this purpose,
but some of it used a more basic StringList class instead. In either
case, the fact that the underlying abstraction did not provide primitive
operations for the typical environment operations meant that even a
simple operation like checking for an environment variable value was
several lines of code.
This patch adds a separate Environment class, which is essentialy a
llvm::StringMap<std::string> in disguise. To standard StringMap
functionality, it adds a couple of new functions, which are specific to
the environment use case:
- (most important) envp conversion for passing into execve() and likes.
Instead of trying to maintain a constantly up-to-date envp view, it
provides a function which creates a envp view on demand, with the
expectation that this will be called as the very last thing before
handing the value to the system function.
- insert(StringRef KeyEqValue) - splits KeyEqValue into (key, value)
pair and inserts it into the environment map.
- compose(value_type KeyValue) - takes a map entry and converts in back
into "KEY=VALUE" representation.
With this interface most of the environment-manipulating code becomes
one-liners. The only tricky part was maintaining compatibility in
SBLaunchInfo, which expects that the environment entries are accessible
by index and that the returned const char* is backed by the launch info
object (random access into maps is hard and the map stores the entry in
a deconstructed form, so we cannot just return a .c_str() value). To
solve this, I have the SBLaunchInfo convert the environment into the
"envp" form, and use it to answer the environment queries. Extra code is
added to make sure the envp version is always in sync.
(This also improves the layering situation as Args was in the Interpreter module
whereas Environment is in Utility.)
Reviewers: zturner, davide, jingham, clayborg
Subscribers: emaste, lldb-commits, mgorny
Differential Revision: https://reviews.llvm.org/D41359
llvm-svn: 322174
2018-01-10 19:57:31 +08:00
env_vars . try_emplace ( " OS_ACTIVITY_DT_MODE " , " enable " ) ;
2016-09-07 04:57:50 +08:00
}
// Let our parent class do the real launching.
return PlatformPOSIX : : LaunchProcess ( launch_info ) ;
2016-07-15 05:02:45 +08:00
}
2017-06-02 13:17:19 +08:00
lldb_private : : Status
PlatformDarwin : : FindBundleBinaryInExecSearchPaths ( const ModuleSpec & module_spec , Process * process ,
ModuleSP & module_sp ,
const FileSpecList * module_search_paths_ptr ,
ModuleSP * old_module_sp_ptr , bool * did_create_ptr )
{
const FileSpec & platform_file = module_spec . GetFileSpec ( ) ;
// See if the file is present in any of the module_search_paths_ptr directories.
if ( ! module_sp & & module_search_paths_ptr & & platform_file ) {
// create a vector of all the file / directory names in platform_file
// e.g. this might be
// /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
//
// We'll need to look in the module_search_paths_ptr directories for
// both "UIFoundation" and "UIFoundation.framework" -- most likely the
// latter will be the one we find there.
FileSpec platform_pull_apart ( platform_file ) ;
std : : vector < std : : string > path_parts ;
ConstString unix_root_dir ( " / " ) ;
while ( true ) {
ConstString part = platform_pull_apart . GetLastPathComponent ( ) ;
platform_pull_apart . RemoveLastPathComponent ( ) ;
if ( part . IsEmpty ( ) | | part = = unix_root_dir )
break ;
path_parts . push_back ( part . AsCString ( ) ) ;
}
const size_t path_parts_size = path_parts . size ( ) ;
size_t num_module_search_paths = module_search_paths_ptr - > GetSize ( ) ;
for ( size_t i = 0 ; i < num_module_search_paths ; + + i ) {
Log * log_verbose = lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_HOST ) ;
if ( log_verbose )
log_verbose - > Printf ( " PlatformRemoteDarwinDevice::GetSharedModule searching for binary in search-path %s " , module_search_paths_ptr - > GetFileSpecAtIndex ( i ) . GetPath ( ) . c_str ( ) ) ;
// Create a new FileSpec with this module_search_paths_ptr
// plus just the filename ("UIFoundation"), then the parent
// dir plus filename ("UIFoundation.framework/UIFoundation")
// etc - up to four names (to handle "Foo.framework/Contents/MacOS/Foo")
for ( size_t j = 0 ; j < 4 & & j < path_parts_size - 1 ; + + j ) {
FileSpec path_to_try ( module_search_paths_ptr - > GetFileSpecAtIndex ( i ) ) ;
// Add the components backwards. For
// .../PrivateFrameworks/UIFoundation.framework/UIFoundation
// path_parts is
// [0] UIFoundation
// [1] UIFoundation.framework
// [2] PrivateFrameworks
//
// and if 'j' is 2, we want to append path_parts[1] and then
// path_parts[0], aka
// 'UIFoundation.framework/UIFoundation', to the module_search_paths_ptr
// path.
for ( int k = j ; k > = 0 ; - - k ) {
path_to_try . AppendPathComponent ( path_parts [ k ] ) ;
}
if ( path_to_try . Exists ( ) ) {
ModuleSpec new_module_spec ( module_spec ) ;
new_module_spec . GetFileSpec ( ) = path_to_try ;
Status new_error ( Platform : : GetSharedModule (
new_module_spec , process , module_sp , NULL , old_module_sp_ptr ,
did_create_ptr ) ) ;
if ( module_sp ) {
module_sp - > SetPlatformFileSpec ( path_to_try ) ;
return new_error ;
}
}
}
}
}
return Status ( ) ;
}