summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Host/Host.h49
-rw-r--r--lldb/include/lldb/lldb-enumerations.h13
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj112
-rw-r--r--lldb/source/Core/FileSpec.cpp55
-rw-r--r--lldb/source/Expression/IRDynamicChecks.cpp2
-rw-r--r--lldb/source/Host/common/Host.cpp153
-rw-r--r--lldb/source/Host/macosx/Host.mm156
-rw-r--r--lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp43
-rw-r--r--lldb/source/Host/macosx/cfcpp/CFCMutableArray.h5
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterPython.cpp61
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp73
-rw-r--r--lldb/source/Target/Target.cpp2
-rw-r--r--lldb/source/Target/TargetList.cpp2
-rw-r--r--lldb/tools/darwin-debug/darwin-debug.cpp221
-rw-r--r--lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj1
15 files changed, 834 insertions, 114 deletions
diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h
index cbd29cc4c89..9d0882a36e7 100644
--- a/lldb/include/lldb/Host/Host.h
+++ b/lldb/include/lldb/Host/Host.h
@@ -256,8 +256,46 @@ public:
static FileSpec
GetModuleFileSpecForHostAddress (const void *host_addr);
+
+ //------------------------------------------------------------------
+ /// When executable files may live within a directory, where the
+ /// directory represents an executable bundle (like the MacOSX
+ /// app bundles), the locate the executable within the containing
+ /// bundle.
+ ///
+ /// @param[in,out] file
+ /// A file spec that currently points to the bundle that will
+ /// be filled in with the executable path within the bundle
+ /// if \b true is returned. Otherwise \a file is left untouched.
+ ///
+ /// @return
+ /// \b true if \a file was resolved, \b false if this function
+ /// was not able to resolve the path.
+ //------------------------------------------------------------------
static bool
- ResolveExecutableInBundle (FileSpec *file);
+ ResolveExecutableInBundle (FileSpec &file);
+
+ //------------------------------------------------------------------
+ /// Find a resource files that are related to LLDB.
+ ///
+ /// Operating systems have different ways of storing shared
+ /// libraries and related resources. This function abstracts the
+ /// access to these paths.
+ ///
+ /// @param[in] path_type
+ /// The type of LLDB resource path you are looking for. If the
+ /// enumeration ends with "Dir", then only the \a file_spec's
+ /// directory member gets filled in.
+ ///
+ /// @param[in] file_spec
+ /// A file spec that gets filled in with the appriopriate path.
+ ///
+ /// @return
+ /// \b true if \a resource_path was resolved, \a false otherwise.
+ //------------------------------------------------------------------
+ static bool
+ GetLLDBPath (lldb::PathType path_type,
+ FileSpec &file_spec);
static uint32_t
ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids);
@@ -269,7 +307,14 @@ public:
GetArchSpecForExistingProcess (const char *process_name);
static lldb::pid_t
- LaunchApplication (const FileSpec &file_spec);
+ LaunchApplication (const FileSpec &app_file_spec);
+
+ static lldb::pid_t
+ LaunchInNewTerminal (const char **argv, // argv[0] is executable
+ const char **envp,
+ const ArchSpec *arch_spec,
+ bool stop_at_entry,
+ bool disable_aslr);
static bool
OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no);
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 5326fcc2f2d..ef6c03a6779 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -597,6 +597,19 @@ typedef enum SortOrder
eSortOrderByName,
} SortOrder;
+
+//----------------------------------------------------------------------
+// Used in conjunction with Host::GetLLDBResource () to find files that
+// are related to
+//----------------------------------------------------------------------
+typedef enum PathType
+{
+ ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists
+ ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc)
+ ePathTypeHeaderDir, // Find LLDB header file directory
+ ePathTypePythonDir // Find Python modules (PYTHONPATH) directory
+} PathType;
+
} // namespace lldb
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 59044ae4173..223b7cb504b 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -21,6 +21,8 @@
261B5A5411C3F2AD00AABD0A /* SharingPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */; };
261B5A5511C3F2AD00AABD0A /* SharingPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */; settings = {ATTRIBUTES = (Public, ); }; };
262CFC7711A4510000946C6C /* debugserver in Resources */ = {isa = PBXBuildFile; fileRef = 26CE05A0115C31E50022F371 /* debugserver */; };
+ 26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26368A3B126B697600E8659F /* darwin-debug.cpp */; };
+ 26368AF7126B960500E8659F /* darwin-debug in Resources */ = {isa = PBXBuildFile; fileRef = 26579F68126A25920007C5CB /* darwin-debug */; };
26424E3D125986CB0016D82C /* ValueObjectConstResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */; };
26424E3F125986D30016D82C /* ValueObjectConstResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 26424E3E125986D30016D82C /* ValueObjectConstResult.h */; };
264723A611FA076E00DE380C /* CleanUp.h in Headers */ = {isa = PBXBuildFile; fileRef = 264723A511FA076E00DE380C /* CleanUp.h */; };
@@ -415,6 +417,13 @@
remoteGlobalIDString = 26CE0593115C31C20022F371;
remoteInfo = debugserver;
};
+ 26368AF5126B95FA00E8659F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 26579F67126A25920007C5CB /* darwin-debug */;
+ remoteInfo = "darwin-debug";
+ };
266803611160110D008E1FE4 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -562,6 +571,7 @@
261E18CD1148966100BADCD3 /* GDBRemoteRegisterContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GDBRemoteRegisterContext.cpp; path = "source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp"; sourceTree = "<group>"; };
263664921140A4930075843B /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Debugger.cpp; path = source/Core/Debugger.cpp; sourceTree = "<group>"; };
263664941140A4C10075843B /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Debugger.h; path = include/lldb/Core/Debugger.h; sourceTree = "<group>"; };
+ 26368A3B126B697600E8659F /* darwin-debug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "darwin-debug.cpp"; path = "tools/darwin-debug/darwin-debug.cpp"; sourceTree = "<group>"; };
263FEDA5112CC1DA00E4C208 /* ThreadSafeSTLMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSafeSTLMap.h; path = include/lldb/Core/ThreadSafeSTLMap.h; sourceTree = "<group>"; };
26424E3C125986CB0016D82C /* ValueObjectConstResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectConstResult.cpp; path = source/Core/ValueObjectConstResult.cpp; sourceTree = "<group>"; };
26424E3E125986D30016D82C /* ValueObjectConstResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectConstResult.h; path = include/lldb/Core/ValueObjectConstResult.h; sourceTree = "<group>"; };
@@ -570,6 +580,7 @@
264723A511FA076E00DE380C /* CleanUp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CleanUp.h; path = include/lldb/Utility/CleanUp.h; sourceTree = "<group>"; };
264AD83711095BA600E0B039 /* CommandObjectLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectLog.cpp; path = source/Commands/CommandObjectLog.cpp; sourceTree = "<group>"; };
264AD83911095BBD00E0B039 /* CommandObjectLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectLog.h; path = source/Commands/CommandObjectLog.h; sourceTree = "<group>"; };
+ 26579F68126A25920007C5CB /* darwin-debug */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "darwin-debug"; sourceTree = BUILT_PRODUCTS_DIR; };
265ABF6210F42EE900531910 /* DebugSymbols.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DebugSymbols.framework; path = /System/Library/PrivateFrameworks/DebugSymbols.framework; sourceTree = "<absolute>"; };
265E9BE1115C2BAA00D0DCCB /* debugserver.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = debugserver.xcodeproj; path = tools/debugserver/debugserver.xcodeproj; sourceTree = "<group>"; };
2660D9F611922A1300958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = source/Utility/StringExtractor.cpp; sourceTree = "<group>"; };
@@ -1123,6 +1134,13 @@
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
+ 26579F66126A25920007C5CB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
26680205115FD0ED008E1FE4 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -1196,6 +1214,7 @@
children = (
26F5C26A10F3D9A4009D5894 /* lldb */,
26680207115FD0ED008E1FE4 /* LLDB.framework */,
+ 26579F68126A25920007C5CB /* darwin-debug */,
);
name = Products;
sourceTree = "<group>";
@@ -1543,6 +1562,14 @@
name = API;
sourceTree = "<group>";
};
+ 26579F55126A255E0007C5CB /* darwin-debug */ = {
+ isa = PBXGroup;
+ children = (
+ 26368A3B126B697600E8659F /* darwin-debug.cpp */,
+ );
+ name = "darwin-debug";
+ sourceTree = "<group>";
+ };
265E9BE0115C2B8500D0DCCB /* debugserver */ = {
isa = PBXGroup;
children = (
@@ -2112,6 +2139,7 @@
26F5C22410F3D950009D5894 /* Tools */ = {
isa = PBXGroup;
children = (
+ 26579F55126A255E0007C5CB /* darwin-debug */,
265E9BE0115C2B8500D0DCCB /* debugserver */,
26F5C22510F3D956009D5894 /* Driver */,
);
@@ -2397,6 +2425,22 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
+ 26579F67126A25920007C5CB /* darwin-debug */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 26579F6D126A25BF0007C5CB /* Build configuration list for PBXNativeTarget "darwin-debug" */;
+ buildPhases = (
+ 26579F65126A25920007C5CB /* Sources */,
+ 26579F66126A25920007C5CB /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "darwin-debug";
+ productName = "lldb-launcher";
+ productReference = 26579F68126A25920007C5CB /* darwin-debug */;
+ productType = "com.apple.product-type.tool";
+ };
26680206115FD0ED008E1FE4 /* LLDB */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2668020B115FD0EE008E1FE4 /* Build configuration list for PBXNativeTarget "LLDB" */;
@@ -2414,6 +2458,7 @@
);
dependencies = (
262CFC7211A450CB00946C6C /* PBXTargetDependency */,
+ 26368AF6126B95FA00E8659F /* PBXTargetDependency */,
);
name = LLDB;
productName = LLDB;
@@ -2462,6 +2507,7 @@
targets = (
26F5C26910F3D9A4009D5894 /* lldb-tool */,
26680206115FD0ED008E1FE4 /* LLDB */,
+ 26579F67126A25920007C5CB /* darwin-debug */,
);
};
/* End PBXProject section */
@@ -2482,6 +2528,7 @@
buildActionMask = 2147483647;
files = (
262CFC7711A4510000946C6C /* debugserver in Resources */,
+ 26368AF7126B960500E8659F /* darwin-debug in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2557,6 +2604,14 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 26579F65126A25920007C5CB /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 26368A3C126B697600E8659F /* darwin-debug.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
26680204115FD0ED008E1FE4 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -2885,6 +2940,11 @@
name = debugserver;
targetProxy = 262CFC7111A450CB00946C6C /* PBXContainerItemProxy */;
};
+ 26368AF6126B95FA00E8659F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 26579F67126A25920007C5CB /* darwin-debug */;
+ targetProxy = 26368AF5126B95FA00E8659F /* PBXContainerItemProxy */;
+ };
266803621160110D008E1FE4 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 26680206115FD0ED008E1FE4 /* LLDB */;
@@ -2944,6 +3004,48 @@
};
name = Release;
};
+ 26579F6A126A25920007C5CB /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = "darwin-debug";
+ };
+ name = Debug;
+ };
+ 26579F6B126A25920007C5CB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = "darwin-debug";
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ 26579F6C126A25920007C5CB /* BuildAndIntegration */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = "darwin-debug";
+ };
+ name = BuildAndIntegration;
+ };
26680209115FD0ED008E1FE4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -3251,6 +3353,16 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = BuildAndIntegration;
};
+ 26579F6D126A25BF0007C5CB /* Build configuration list for PBXNativeTarget "darwin-debug" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 26579F6A126A25920007C5CB /* Debug */,
+ 26579F6B126A25920007C5CB /* Release */,
+ 26579F6C126A25920007C5CB /* BuildAndIntegration */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = BuildAndIntegration;
+ };
2668020B115FD0EE008E1FE4 /* Build configuration list for PBXNativeTarget "LLDB" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/lldb/source/Core/FileSpec.cpp b/lldb/source/Core/FileSpec.cpp
index 45cfc120a4b..1768a063035 100644
--- a/lldb/source/Core/FileSpec.cpp
+++ b/lldb/source/Core/FileSpec.cpp
@@ -574,42 +574,37 @@ FileSpec::GetFilename() const
bool
FileSpec::GetPath(char *path, size_t max_path_length) const
{
- if (max_path_length == 0)
- return false;
-
- path[0] = '\0';
- const char *dirname = m_directory.AsCString();
- const char *filename = m_filename.AsCString();
- if (dirname)
+ if (max_path_length)
{
- if (filename && filename[0])
+ const char *dirname = m_directory.AsCString();
+ const char *filename = m_filename.AsCString();
+ if (dirname)
{
- return (size_t)::snprintf (path, max_path_length, "%s/%s", dirname, filename) < max_path_length;
+ if (filename)
+ {
+ return (size_t)::snprintf (path, max_path_length, "%s/%s", dirname, filename) < max_path_length;
+ }
+ else
+ {
+ size_t dir_len = m_directory.GetLength() + 1;
+ if (dir_len < max_path_length)
+ {
+ ::memcpy (path, dirname, dir_len);
+ return true;
+ }
+ }
}
- else
+ else if (filename)
{
- ::strncpy (path, dirname, max_path_length);
+ size_t filename_len = m_filename.GetLength() + 1;
+ if (filename_len < max_path_length)
+ {
+ ::memcpy (path, filename, filename_len);
+ return true;
+ }
}
}
- else if (filename)
- {
- ::strncpy (path, filename, max_path_length);
- }
- else
- {
- return false;
- }
-
- // Any code paths that reach here assume that strncpy, or a similar function was called
- // where any remaining bytes will be filled with NULLs and that the string won't be
- // NULL terminated if it won't fit in the buffer.
-
- // If the last character is NULL, then all went well
- if (path[max_path_length-1] == '\0')
- return true;
-
- // Make sure the path is terminated, as it didn't fit into "path"
- path[max_path_length-1] = '\0';
+ path[0] = '\0';
return false;
}
diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp
index 16e5d3d3f01..ca2f8d0af57 100644
--- a/lldb/source/Expression/IRDynamicChecks.cpp
+++ b/lldb/source/Expression/IRDynamicChecks.cpp
@@ -33,7 +33,7 @@ static const char g_valid_pointer_check_text[] =
"extern \"C\" void\n"
"$__lldb_valid_pointer_check (unsigned char *$__lldb_arg_ptr)\n"
"{\n"
-" unsigned char $__lldb_local_val = *__lldb_arg_ptr;\n"
+" unsigned char $__lldb_local_val = *$__lldb_arg_ptr;\n"
"}";
static bool FunctionExists(const SymbolContext &sym_ctx, const char *name)
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 16e1ea9459a..ea96e65f6cb 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -626,12 +626,140 @@ Host::GetModuleFileSpecForHostAddress (const void *host_addr)
#if !defined (__APPLE__) // see Host.mm
bool
-Host::ResolveExecutableInBundle (FileSpec *file)
+Host::ResolveExecutableInBundle (FileSpec &file)
{
- return false;
+ return false;
}
#endif
+
+bool
+Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
+{
+ // To get paths related to LLDB we get the path to the exectuable that
+ // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
+ // on linux this is assumed to be the "lldb" main executable. If LLDB on
+ // linux is actually in a shared library (lldb.so??) then this function will
+ // need to be modified to "do the right thing".
+
+ switch (path_type)
+ {
+ case ePathTypeLLDBShlibDir:
+ {
+ static ConstString g_lldb_so_dir;
+ if (!g_lldb_so_dir)
+ {
+ FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
+ g_lldb_so_dir = lldb_file_spec.GetDirectory();
+ }
+ file_spec.GetDirectory() = g_lldb_so_dir;
+ return file_spec.GetDirectory();
+ }
+ break;
+
+ case ePathTypeSupportExecutableDir:
+ {
+ static ConstString g_lldb_support_exe_dir;
+ if (!g_lldb_support_exe_dir)
+ {
+ FileSpec lldb_file_spec;
+ if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
+ {
+ char raw_path[PATH_MAX];
+ char resolved_path[PATH_MAX];
+ lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+
+#if defined (__APPLE__)
+ char *framework_pos = ::strstr (raw_path, "LLDB.framework");
+ if (framework_pos)
+ {
+ framework_pos += strlen("LLDB.framework");
+ ::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
+ }
+#endif
+ FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
+ g_lldb_support_exe_dir.SetCString(resolved_path);
+ }
+ }
+ file_spec.GetDirectory() = g_lldb_support_exe_dir;
+ return file_spec.GetDirectory();
+ }
+ break;
+
+ case ePathTypeHeaderDir:
+ {
+ static ConstString g_lldb_headers_dir;
+ if (!g_lldb_headers_dir)
+ {
+#if defined (__APPLE__)
+ FileSpec lldb_file_spec;
+ if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
+ {
+ char raw_path[PATH_MAX];
+ char resolved_path[PATH_MAX];
+ lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+
+ char *framework_pos = ::strstr (raw_path, "LLDB.framework");
+ if (framework_pos)
+ {
+ framework_pos += strlen("LLDB.framework");
+ ::strncpy (framework_pos, "/Headers", PATH_MAX - (framework_pos - raw_path));
+ }
+ FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
+ g_lldb_headers_dir.SetCString(resolved_path);
+ }
+#else
+ // TODO: Anyone know how we can determine this for linux??
+ g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
+#endif
+ }
+ file_spec.GetDirectory() = g_lldb_headers_dir;
+ return file_spec.GetDirectory();
+ }
+ break;
+
+ case ePathTypePythonDir:
+ {
+ // TODO: Anyone know how we can determine this for linux??
+ // For linux we are currently assuming the location of the lldb
+ // binary that contains this function is the directory that will
+ // contain lldb.so, lldb.py and embedded_interpreter.py...
+
+ static ConstString g_lldb_python_dir;
+ if (!g_lldb_python_dir)
+ {
+ FileSpec lldb_file_spec;
+ if (GetLLDBPath (ePathTypeLLDBShlibDir, lldb_file_spec))
+ {
+ char raw_path[PATH_MAX];
+ char resolved_path[PATH_MAX];
+ lldb_file_spec.GetPath(raw_path, sizeof(raw_path));
+
+#if defined (__APPLE__)
+ char *framework_pos = ::strstr (raw_path, "LLDB.framework");
+ if (framework_pos)
+ {
+ framework_pos += strlen("LLDB.framework");
+ ::strncpy (framework_pos, "/Resources/Python", PATH_MAX - (framework_pos - raw_path));
+ }
+#endif
+ FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
+ g_lldb_python_dir.SetCString(resolved_path);
+ }
+ }
+ file_spec.GetDirectory() = g_lldb_python_dir;
+ return file_spec.GetDirectory();
+ }
+ break;
+
+ default:
+ assert (!"Unhandled PathType");
+ break;
+ }
+
+ return false;
+}
+
uint32_t
Host::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
{
@@ -727,4 +855,25 @@ Host::OpenFileInExternalEditor (FileSpec &file_spec, uint32_t line_no)
{
return false;
}
+
+
+lldb::pid_t
+LaunchApplication (const FileSpec &app_file_spec)
+{
+ return LLDB_INVALID_PROCESS_ID;
+}
+
+lldb::pid_t
+Host::LaunchInNewTerminal
+(
+ const char **argv,
+ const char **envp,
+ const ArchSpec *arch_spec,
+ bool stop_at_entry,
+ bool disable_aslr
+)
+{
+ return LLDB_INVALID_PROCESS_ID;
+}
+
#endif
diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm
index e3379d07cca..298aec4029c 100644
--- a/lldb/source/Host/macosx/Host.mm
+++ b/lldb/source/Host/macosx/Host.mm
@@ -8,10 +8,18 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Host.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/FileSpec.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
#include "cfcpp/CFCBundle.h"
+#include "cfcpp/CFCMutableArray.h"
#include "cfcpp/CFCMutableDictionary.h"
#include "cfcpp/CFCReleaser.h"
#include "cfcpp/CFCString.h"
@@ -90,26 +98,26 @@ Host::ThreadCreated (const char *thread_name)
bool
-Host::ResolveExecutableInBundle (FileSpec *file)
+Host::ResolveExecutableInBundle (FileSpec &file)
{
#if defined (__APPLE__)
- if (file->GetFileType () == FileSpec::eFileTypeDirectory)
- {
- char path[PATH_MAX];
- if (file->GetPath(path, sizeof(path)))
+ if (file.GetFileType () == FileSpec::eFileTypeDirectory)
{
- CFCBundle bundle (path);
- CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
- if (url.get())
- {
- if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
+ char path[PATH_MAX];
+ if (file.GetPath(path, sizeof(path)))
{
- file->SetFile(path);
- return true;
+ CFCBundle bundle (path);
+ CFCReleaser<CFURLRef> url(bundle.CopyExecutableURL ());
+ if (url.get())
+ {
+ if (::CFURLGetFileSystemRepresentation (url.get(), YES, (UInt8*)path, sizeof(path)))
+ {
+ file.SetFile(path);
+ return true;
+ }
+ }
}
- }
}
- }
#endif
return false;
}
@@ -124,8 +132,8 @@ Host::LaunchApplication (const FileSpec &app_file_spec)
::bzero (&app_params, sizeof (app_params));
app_params.flags = kLSLaunchDefaults |
kLSLaunchDontAddToRecents |
- kLSLaunchDontSwitch |
- kLSLaunchNewInstance;// | 0x00001000;
+ kLSLaunchNewInstance;
+
FSRef app_fsref;
CFCString app_cfstr (app_path, kCFStringEncodingUTF8);
@@ -150,6 +158,122 @@ Host::LaunchApplication (const FileSpec &app_file_spec)
return pid;
}
+lldb::pid_t
+Host::LaunchInNewTerminal
+(
+ const char **argv,
+ const char **envp,
+ const ArchSpec *arch_spec,
+ bool stop_at_entry,
+ bool disable_aslr
+)
+{
+ if (!argv || !argv[0])
+ return LLDB_INVALID_PROCESS_ID;
+
+ OSStatus error = 0;
+
+ FileSpec program (argv[0]);
+
+
+ char temp_file_path[PATH_MAX];
+ const char *tmpdir = ::getenv ("TMPDIR");
+ if (tmpdir == NULL)
+ tmpdir = "/tmp/";
+ ::snprintf (temp_file_path, sizeof(temp_file_path), "%s%s-XXXXXX", tmpdir, program.GetFilename().AsCString());
+
+ if (::mktemp (temp_file_path) == NULL)
+ return LLDB_INVALID_PROCESS_ID;
+
+ ::strncat (temp_file_path, ".command", sizeof (temp_file_path));
+
+ StreamFile command_file (temp_file_path, "w");
+
+ FileSpec darwin_debug_file_spec;
+ if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
+ return LLDB_INVALID_PROCESS_ID;
+ darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
+
+ if (!darwin_debug_file_spec.Exists())
+ return LLDB_INVALID_PROCESS_ID;
+
+ char launcher_path[PATH_MAX];
+ darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
+ command_file.Printf("\"%s\" ", launcher_path);
+
+ if (arch_spec && arch_spec->IsValid())
+ {
+ command_file.Printf("--arch=%s ", arch_spec->AsCString());
+ }
+
+ if (disable_aslr)
+ {
+ command_file.PutCString("--disable-aslr ");
+ }
+
+ command_file.PutCString("-- ");
+
+ if (argv)
+ {
+ for (size_t i=0; argv[i] != NULL; ++i)
+ {
+ command_file.Printf("\"%s\" ", argv[i]);
+ }
+ }
+ command_file.EOL();
+ command_file.Close();
+ if (::chmod (temp_file_path, S_IRWXU | S_IRWXG) != 0)
+ return LLDB_INVALID_PROCESS_ID;
+
+ CFCMutableDictionary cf_env_dict;
+
+ const bool can_create = true;
+ if (envp)
+ {
+ for (size_t i=0; envp[i] != NULL; ++i)
+ {
+ const char *env_entry = envp[i];
+ const char *equal_pos = strchr(env_entry, '=');
+ if (equal_pos)
+ {
+ std::string env_key (env_entry, equal_pos);
+ std::string env_val (equal_pos + 1);
+ CFCString cf_env_key (env_key.c_str(), kCFStringEncodingUTF8);
+ CFCString cf_env_val (env_val.c_str(), kCFStringEncodingUTF8);
+ cf_env_dict.AddValue (cf_env_key.get(), cf_env_val.get(), can_create);
+ }
+ }
+ }
+
+ LSApplicationParameters app_params;
+ ::bzero (&app_params, sizeof (app_params));
+ app_params.flags = kLSLaunchDontAddToRecents | kLSLaunchAsync;
+ app_params.argv = NULL;
+ app_params.environment = (CFDictionaryRef)cf_env_dict.get();
+
+ CFCReleaser<CFURLRef> command_file_url (::CFURLCreateFromFileSystemRepresentation (NULL,
+ (const UInt8 *)temp_file_path,
+ strlen (temp_file_path),
+ false));
+
+ CFCMutableArray urls;
+
+ // Terminal.app will open the ".command" file we have created
+ // and run our process inside it which will wait at the entry point
+ // for us to attach.
+ urls.AppendValue(command_file_url.get());
+
+ ProcessSerialNumber psn;
+ error = LSOpenURLsWithRole(urls.get(), kLSRolesShell, NULL, &app_params, &psn, 1);
+
+ if (error != noErr)
+ return LLDB_INVALID_PROCESS_ID;
+
+ ::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ error = ::GetProcessPID(&psn, &pid);
+ return pid;
+}
+
bool
Host::OpenFileInExternalEditor (const FileSpec &file_spec, uint32_t line_no)
{
diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp
index 3b92f03fa61..c3c0a11193a 100644
--- a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp
+++ b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "CFCMutableArray.h"
+#include "CFCString.h"
//----------------------------------------------------------------------
// CFCString constructor
@@ -121,3 +122,45 @@ CFCMutableArray::AppendValue(const void *value, bool can_create)
}
return false;
}
+
+
+bool
+CFCMutableArray::AppendCStringAsCFString (const char *s, CFStringEncoding encoding, bool can_create)
+{
+ CFMutableArrayRef array = get();
+ if (array == NULL)
+ {
+ if (can_create == false)
+ return false;
+ array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ reset ( array );
+ }
+ if (array != NULL)
+ {
+ CFCString cf_str (s, encoding);
+ ::CFArrayAppendValue (array, cf_str.get());
+ return true;
+ }
+ return false;
+}
+
+bool
+CFCMutableArray::AppendFileSystemRepresentationAsCFString (const char *s, bool can_create)
+{
+ CFMutableArrayRef array = get();
+ if (array == NULL)
+ {
+ if (can_create == false)
+ return false;
+ array = ::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ reset ( array );
+ }
+ if (array != NULL)
+ {
+ CFCString cf_path;
+ cf_path.SetFileSystemRepresentation(s);
+ ::CFArrayAppendValue (array, cf_path.get());
+ return true;
+ }
+ return false;
+}
diff --git a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h
index eaadb8d5590..f78cd92ffab 100644
--- a/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h
+++ b/lldb/source/Host/macosx/cfcpp/CFCMutableArray.h
@@ -29,6 +29,11 @@ public:
const void * GetValueAtIndex(CFIndex idx) const;
bool SetValueAtIndex(CFIndex idx, const void *value);
bool AppendValue(const void *value, bool can_create = true); // Appends value and optionally creates a CFCMutableArray if this class doesn't contain one
+ bool AppendCStringAsCFString (const char *cstr,
+ CFStringEncoding encoding = kCFStringEncodingUTF8,
+ bool can_create = true);
+ bool AppendFileSystemRepresentationAsCFString (const char *s,
+ bool can_create = true);
};
#endif // #ifndef CoreFoundationCPP_CFMutableArray_h_
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
index 42d2ef46438..9520150efab 100644
--- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -164,34 +164,42 @@ ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interprete
// Find the module that owns this code and use that path we get to
// set the PYTHONPATH appropriately.
- FileSpec this_module (Host::GetModuleFileSpecForHostAddress ((void *)init_lldb));
- std::string python_path;
-
- if (this_module.GetDirectory())
+ FileSpec file_spec;
+ char python_dir_path[PATH_MAX];
+ if (Host::GetLLDBPath (ePathTypePythonDir, file_spec))
{
- // Append the directory that the module that loaded this code
- // belongs to
- python_path += this_module.GetDirectory().AsCString("");
-
-#if defined (__APPLE__)
- // If we are running on MacOSX we might be in a framework and should
- // add an appropriate path so Resource can be found in a bundle
+ std::string python_path;
+ const char *curr_python_path = ::getenv ("PYTHONPATH");
+ if (curr_python_path)
+ {
+ // We have a current value for PYTHONPATH, so lets append to it
+ python_path.append (curr_python_path);
+ }
- if (::strstr(this_module.GetDirectory().AsCString(""), ".framework"))
+ if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
+ {
+ if (!python_path.empty())
+ python_path.append (1, ':');
+ python_path.append (python_dir_path);
+ }
+
+ if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, file_spec))
{
- python_path.append(1, ':');
- python_path.append(this_module.GetDirectory().AsCString(""));
- python_path.append("/Resources/Python");
+ if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
+ {
+ if (!python_path.empty())
+ python_path.append (1, ':');
+ python_path.append (python_dir_path);
+ }
}
-#endif
- // The the PYTHONPATH environment variable so that Python can find
- // our lldb.py module and our _lldb.so.
- ::setenv ("PYTHONPATH", python_path.c_str(), 1);
+ const char *pathon_path_env_cstr = python_path.c_str();
+ ::setenv ("PYTHONPATH", pathon_path_env_cstr, 1);
}
Py_Initialize ();
- PyObject *compiled_module = Py_CompileString (embedded_interpreter_string, "embedded_interpreter.py",
+ PyObject *compiled_module = Py_CompileString (embedded_interpreter_string,
+ "embedded_interpreter.py",
Py_file_input);
m_compiled_module = static_cast<void*>(compiled_module);
@@ -310,14 +318,15 @@ ScriptInterpreterPython::InputReaderCallback
int input_fd;
FILE *input_fh = reader.GetDebugger().GetInputFileHandle();
if (input_fh != NULL)
- input_fd = ::fileno (input_fh);
+ input_fd = ::fileno (input_fh);
else
- input_fd = STDIN_FILENO;
+ input_fd = STDIN_FILENO;
script_interpreter->m_termios_valid = ::tcgetattr (input_fd, &script_interpreter->m_termios) == 0;
- struct termios tmp_termios;
- if (::tcgetattr (input_fd, &tmp_termios) == 0)
+
+ if (script_interpreter->m_termios_valid)
{
+ struct termios tmp_termios = script_interpreter->m_termios;
tmp_termios.c_cc[VEOF] = _POSIX_VDISABLE;
::tcsetattr (input_fd, TCSANOW, &tmp_termios);
}
@@ -352,9 +361,9 @@ ScriptInterpreterPython::InputReaderCallback
int input_fd;
FILE *input_fh = reader.GetDebugger().GetInputFileHandle();
if (input_fh != NULL)
- input_fd = ::fileno (input_fh);
+ input_fd = ::fileno (input_fh);
else
- input_fd = STDIN_FILENO;
+ input_fd = STDIN_FILENO;
::tcsetattr (input_fd, TCSANOW, &script_interpreter->m_termios);
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index c9b5955ee09..3da1d59aa70 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -384,12 +384,28 @@ ProcessGDBRemote::DoLaunch
{
Error error;
#if defined (LAUNCH_WITH_LAUNCH_SERVICES)
- FileSpec app_file_spec (argv[0]);
- pid_t pid = Host::LaunchApplication (app_file_spec);
+ ArchSpec inferior_arch(module->GetArchitecture());
+
+ //FileSpec app_file_spec (argv[0]);
+ pid_t pid = Host::LaunchInNewTerminal (argv,
+ envp,
+ &inferior_arch,
+ true, // stop at entry
+ (launch_flags & eLaunchFlagDisableASLR) != 0);
+
+ // Let the app get launched and stopped...
+ sleep (1);
+
if (pid != LLDB_INVALID_PROCESS_ID)
- error = DoAttachToProcessWithID (pid);
+ {
+ FileSpec program(argv[0]);
+ error = DoAttachToProcessWithName (program.GetFilename().AsCString(), false);
+ //error = DoAttachToProcessWithID (pid);
+ }
else
- error.SetErrorString("failed");
+ {
+ error.SetErrorString("Host::LaunchApplication(() failed to launch process");
+ }
#else
// ::LogSetBitMask (GDBR_LOG_DEFAULT);
// ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
@@ -1683,31 +1699,19 @@ ProcessGDBRemote::StartDebugserverProcess
{
// The debugserver binary is in the LLDB.framework/Resources
// directory.
- FileSpec framework_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)lldb_private::Initialize));
- const char *framework_dir = framework_file_spec.GetDirectory().AsCString();
- const char *lldb_framework = ::strstr (framework_dir, "/LLDB.framework");
-
- if (lldb_framework)
+ if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
{
- int len = lldb_framework - framework_dir + strlen ("/LLDB.framework");
- ::snprintf (debugserver_path,
- sizeof(debugserver_path),
- "%.*s/Resources/%s",
- len,
- framework_dir,
- DEBUGSERVER_BASENAME);
- debugserver_file_spec.SetFile (debugserver_path);
+ debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
debugserver_exists = debugserver_file_spec.Exists();
- }
-
- if (debugserver_exists)
- {
- g_debugserver_file_spec = debugserver_file_spec;
- }
- else
- {
- g_debugserver_file_spec.Clear();
- debugserver_file_spec.Clear();
+ if (debugserver_exists)
+ {
+ g_debugserver_file_spec = debugserver_file_spec;
+ }
+ else
+ {
+ g_debugserver_file_spec.Clear();
+ debugserver_file_spec.Clear();
+ }
}
}
@@ -1731,9 +1735,9 @@ ProcessGDBRemote::StartDebugserverProcess
#if !defined (__arm__)
- // We don't need to do this for ARM, and we really shouldn't now that we
- // have multiple CPU subtypes and no posix_spawnattr call that allows us
- // to set which CPU subtype to launch...
+ // We don't need to do this for ARM, and we really shouldn't now
+ // that we have multiple CPU subtypes and no posix_spawnattr call
+ // that allows us to set which CPU subtype to launch...
if (inferior_arch.GetType() == eArchTypeMachO)
{
cpu_type_t cpu = inferior_arch.GetCPUType();
@@ -1781,10 +1785,11 @@ ProcessGDBRemote::StartDebugserverProcess
// Start args with "debugserver /file/path -r --"
debugserver_args.AppendArgument(debugserver_path);
debugserver_args.AppendArgument(debugserver_url);
- debugserver_args.AppendArgument("--native-regs"); // use native registers, not the GDB registers
- debugserver_args.AppendArgument("--setsid"); // make debugserver run in its own session so
- // signals generated by special terminal key
- // sequences (^C) don't affect debugserver
+ // use native registers, not the GDB registers
+ debugserver_args.AppendArgument("--native-regs");
+ // make debugserver run in its own session so signals generated by
+ // special terminal key sequences (^C) don't affect debugserver
+ debugserver_args.AppendArgument("--setsid");
if (disable_aslr)
debugserver_args.AppendArguments("--disable-aslr");
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 4a5ce2fa21b..943fda41143 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -402,7 +402,7 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
{
FileSpec bundle_executable(executable_sp->GetFileSpec());
- if (Host::ResolveExecutableInBundle (&bundle_executable))
+ if (Host::ResolveExecutableInBundle (bundle_executable))
{
ModuleSP bundle_exe_module_sp(GetSharedModule(bundle_executable,
exe_arch));
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 6033a60cf86..bb99a44bc5d 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -75,7 +75,7 @@ TargetList::CreateTarget
if (!resolved_file.Exists())
resolved_file.ResolveExecutableLocation ();
- if (!Host::ResolveExecutableInBundle (&resolved_file))
+ if (!Host::ResolveExecutableInBundle (resolved_file))
resolved_file = file;
error = ModuleList::GetSharedModule(resolved_file,
diff --git a/lldb/tools/darwin-debug/darwin-debug.cpp b/lldb/tools/darwin-debug/darwin-debug.cpp
new file mode 100644
index 00000000000..f79d837e634
--- /dev/null
+++ b/lldb/tools/darwin-debug/darwin-debug.cpp
@@ -0,0 +1,221 @@
+//===-- Launcher.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//----------------------------------------------------------------------
+// Darwin launch helper
+//
+// This program was written to allow programs to be launched in a new
+// Terminal.app window and have the application be stopped for debugging
+// at the program entry point.
+//
+// Although it uses posix_spawn(), it uses Darwin specific posix spawn
+// attribute flags to accomplish its task. It uses an "exec only" flag
+// which avoids forking this process, and it uses a "stop at entry"
+// flag to stop the program at the entry point.
+//
+// Since it uses darwin specific flags this code should not be compiled
+// on other systems.
+//----------------------------------------------------------------------
+#if defined (__APPLE__)
+
+#include <getopt.h>
+#include <mach/machine.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _POSIX_SPAWN_DISABLE_ASLR
+#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
+#endif
+
+#define streq(a,b) strcmp(a,b) == 0
+
+static struct option g_long_options[] =
+{
+ { "arch", required_argument, NULL, 'a' },
+ { "disable-aslr", no_argument, NULL, 'd' },
+ { "no-env", no_argument, NULL, 'e' },
+ { "help", no_argument, NULL, 'h' },
+ { "setsid", no_argument, NULL, 's' },
+ { NULL, 0, NULL, 0 }
+};
+
+static void
+usage()
+{
+ puts (
+"NAME\n"
+" darwin-debug -- posix spawn a process that is stopped at the entry point\n"
+" for debugging.\n"
+"\n"
+"SYNOPSIS\n"
+" darwin-debug [--arch=<ARCH>] [--disable-aslr] [--no-env] [--setsid] [--help] -- <PROGRAM> [<PROGRAM-ARG> <PROGRAM-ARG> ....]\n"
+"\n"
+"DESCRIPTION\n"
+" darwin-debug will exec itself into a child process <PROGRAM> that is\n"
+" halted for debugging. It does this by using posix_spawn() along with\n"
+" darwin specific posix_spawn flags that allows exec only (no fork), and\n"
+" stop at the program entry point. Any program arguments <PROGRAM-ARG> are\n"
+" passed on to the exec as the arguments for the new process. The current\n"
+" environment will be passed to the new process unless the \"--no-env\"\n"
+" option is used.\n"
+"\n"
+"EXAMPLE\n"
+" darwin-debug --arch=i386 -- /bin/ls -al /tmp\n"
+);
+ exit (1);
+}
+
+static void
+exit_with_errno (int err, const char *prefix)
+{
+ if (err)
+ {
+ fprintf (stderr,
+ "%s%s",
+ prefix ? prefix : "",
+ strerror(err));
+ exit (err);
+ }
+}
+
+pid_t
+posix_spawn_for_debug (const char *path, char *const *argv, char *const *envp, cpu_type_t cpu_type, int disable_aslr)
+{
+ pid_t pid = 0;
+
+ posix_spawnattr_t attr;
+
+ exit_with_errno (::posix_spawnattr_init (&attr), "::posix_spawnattr_init (&attr) error: ");
+
+ // Here we are using a darwin specific feature that allows us to exec only
+ // since we want this program to turn into the program we want to debug,
+ // and also have the new program start suspended (right at __dyld_start)
+ // so we can debug it
+ short flags = POSIX_SPAWN_START_SUSPENDED | POSIX_SPAWN_SETEXEC;
+
+ // Disable ASLR if we were asked to
+ if (disable_aslr)
+ flags |= _POSIX_SPAWN_DISABLE_ASLR;
+
+ // Set the flags we just made into our posix spawn attributes
+ exit_with_errno (::posix_spawnattr_setflags (&attr, flags), "::posix_spawnattr_setflags (&attr, flags) error: ");
+
+
+ // Another darwin specific thing here where we can select the architecture
+ // of the binary we want to re-exec as.
+ if (cpu_type != 0)
+ {
+ size_t ocount = 0;
+ exit_with_errno (::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), "posix_spawnattr_setbinpref_np () error: ");
+ }
+
+ exit_with_errno (::posix_spawnp (&pid, path, NULL, &attr, (char * const*)argv, (char * const*)envp), "posix_spawn() error: ");
+
+ // This code will only be reached if the posix_spawn exec failed...
+ ::posix_spawnattr_destroy (&attr);
+
+ return pid;
+}
+
+
+int main (int argc, char *const *argv, char *const *envp, const char **apple)
+{
+ const char *program_name = strrchr(apple[0], '/');
+
+ if (program_name)
+ program_name++; // Skip the last slash..
+ else
+ program_name = apple[0];
+
+#if defined (DEBUG_LLDB_LAUNCHER)
+ printf("%s called with:\n", program_name);
+ for (int i=0; i<argc; ++i)
+ printf("argv[%u] = '%s'\n", i, argv[i]);
+#endif
+
+ cpu_type_t cpu_type = 0;
+ bool show_usage = false;
+ char ch;
+ int disable_aslr = 0; // By default we disable ASLR
+ int pass_env = 1;
+ while ((ch = getopt_long(argc, argv, "a:dfh?", g_long_options, NULL)) != -1)
+ {
+ switch (ch)
+ {
+ case 0:
+ break;
+
+ case 'a': // "-a i386" or "--arch=i386"
+ if (optarg)
+ {
+ if (streq (optarg, "i386"))
+ cpu_type = CPU_TYPE_I386;
+ else if (streq (optarg, "x86_64"))
+ cpu_type = CPU_TYPE_X86_64;
+ else if (strstr (optarg, "arm") == optarg)
+ cpu_type = CPU_TYPE_ARM;
+ else
+ {
+ ::fprintf (stderr, "error: unsupported cpu type '%s'\n", optarg);
+ ::exit (1);
+ }
+ }
+ break;
+
+ case 'd':
+ disable_aslr = 1;
+ break;
+
+ case 'e':
+ pass_env = 0;
+ break;
+
+ case 's':
+ // Create a new session to avoid having control-C presses kill our current
+ // terminal session when this program is launched from a .command file
+ ::setsid();
+ break;
+
+ case 'h':
+ case '?':
+ default:
+ show_usage = true;
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (show_usage || argc <= 0)
+ usage();
+
+#if defined (DEBUG_LLDB_LAUNCHER)
+ printf ("\n%s post options:\n", program_name);
+ for (int i=0; i<argc; ++i)
+ printf ("argv[%u] = '%s'\n", i, argv[i]);
+#endif
+
+ const char *exe_path = argv[0];
+
+ // Skip this inferior program name...
+ ++argv;
+
+ posix_spawn_for_debug (exe_path,
+ argv,
+ pass_env ? envp : NULL,
+ cpu_type,
+ disable_aslr);
+
+ return 0;
+}
+
+#endif // #if defined (__APPLE__)
+
diff --git a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj
index 9cbe29e084b..6c5d9738175 100644
--- a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj
+++ b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj
@@ -369,7 +369,6 @@
isa = PBXProject;
buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "debugserver" */;
compatibilityVersion = "Xcode 3.1";
- developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
OpenPOWER on IntegriCloud