diff options
-rw-r--r-- | lldb/include/lldb/Host/Host.h | 49 | ||||
-rw-r--r-- | lldb/include/lldb/lldb-enumerations.h | 13 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 112 | ||||
-rw-r--r-- | lldb/source/Core/FileSpec.cpp | 55 | ||||
-rw-r--r-- | lldb/source/Expression/IRDynamicChecks.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Host/common/Host.cpp | 153 | ||||
-rw-r--r-- | lldb/source/Host/macosx/Host.mm | 156 | ||||
-rw-r--r-- | lldb/source/Host/macosx/cfcpp/CFCMutableArray.cpp | 43 | ||||
-rw-r--r-- | lldb/source/Host/macosx/cfcpp/CFCMutableArray.h | 5 | ||||
-rw-r--r-- | lldb/source/Interpreter/ScriptInterpreterPython.cpp | 61 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 73 | ||||
-rw-r--r-- | lldb/source/Target/Target.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Target/TargetList.cpp | 2 | ||||
-rw-r--r-- | lldb/tools/darwin-debug/darwin-debug.cpp | 221 | ||||
-rw-r--r-- | lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj | 1 |
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, |