aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/lldb/API/SBDebugger.h10
-rw-r--r--include/lldb/API/SBError.h1
-rw-r--r--include/lldb/API/SBExpressionOptions.h6
-rw-r--r--include/lldb/API/SBFileSpec.h7
-rw-r--r--include/lldb/API/SBModule.h36
-rw-r--r--include/lldb/API/SBPlatform.h198
-rw-r--r--include/lldb/API/SBTarget.h17
-rw-r--r--include/lldb/API/SBThread.h5
-rw-r--r--include/lldb/Breakpoint/Breakpoint.h18
-rw-r--r--include/lldb/Breakpoint/BreakpointList.h19
-rw-r--r--include/lldb/Breakpoint/BreakpointLocationList.h5
-rw-r--r--include/lldb/Core/Address.h12
-rw-r--r--include/lldb/Core/Debugger.h14
-rw-r--r--include/lldb/Core/Module.h13
-rw-r--r--include/lldb/DataFormatters/CXXFormatterFunctions.h2
-rw-r--r--include/lldb/DataFormatters/FormatCache.h1
-rw-r--r--include/lldb/DataFormatters/FormatClasses.h84
-rw-r--r--include/lldb/DataFormatters/FormatManager.h30
-rw-r--r--include/lldb/DataFormatters/FormatNavigator.h226
-rw-r--r--include/lldb/DataFormatters/TypeCategory.h8
-rw-r--r--include/lldb/Expression/ClangFunction.h227
-rw-r--r--include/lldb/Expression/ClangUserExpression.h4
-rw-r--r--include/lldb/Host/Debug.h406
-rw-r--r--include/lldb/Host/File.h43
-rw-r--r--include/lldb/Host/FileSpec.h17
-rw-r--r--include/lldb/Host/Host.h21
-rw-r--r--include/lldb/Host/OptionParser.h5
-rw-r--r--include/lldb/Interpreter/PythonDataObjects.h6
-rw-r--r--include/lldb/Interpreter/ScriptInterpreterPython.h7
-rw-r--r--include/lldb/Symbol/TypeList.h11
-rw-r--r--include/lldb/Target/ABI.h9
-rw-r--r--include/lldb/Target/LanguageRuntime.h6
-rw-r--r--include/lldb/Target/Platform.h103
-rw-r--r--include/lldb/Target/Process.h27
-rw-r--r--include/lldb/Target/RegisterCheckpoint.h71
-rw-r--r--include/lldb/Target/RegisterContext.h18
-rw-r--r--include/lldb/Target/SystemRuntime.h7
-rw-r--r--include/lldb/Target/Target.h92
-rw-r--r--include/lldb/Target/Thread.h174
-rw-r--r--include/lldb/Target/ThreadList.h11
-rw-r--r--include/lldb/Target/ThreadPlanCallFunction.h32
-rw-r--r--include/lldb/Target/ThreadPlanCallUserExpression.h10
-rw-r--r--include/lldb/Utility/Iterable.h225
-rw-r--r--include/lldb/Utility/PythonPointer.h6
-rw-r--r--include/lldb/lldb-enumerations.h42
-rw-r--r--include/lldb/lldb-forward.h3
-rw-r--r--include/lldb/lldb-private-enumerations.h3
-rw-r--r--include/lldb/lldb-python.h4
-rw-r--r--source/API/SBDebugger.cpp74
-rw-r--r--source/API/SBExpressionOptions.cpp16
-rw-r--r--source/API/SBFileSpec.cpp18
-rw-r--r--source/API/SBModule.cpp21
-rw-r--r--source/API/SBPlatform.cpp632
-rw-r--r--source/API/SBProcess.cpp2
-rw-r--r--source/API/SBStream.cpp2
-rw-r--r--source/API/SBTarget.cpp13
-rw-r--r--source/API/SBThread.cpp41
-rw-r--r--source/Breakpoint/Breakpoint.cpp6
-rw-r--r--source/Breakpoint/BreakpointList.cpp38
-rw-r--r--source/Breakpoint/BreakpointLocation.cpp2
-rw-r--r--source/Breakpoint/BreakpointLocationList.cpp61
-rw-r--r--source/Commands/CommandObjectExpression.cpp14
-rw-r--r--source/Commands/CommandObjectMemory.cpp315
-rw-r--r--source/Commands/CommandObjectPlatform.cpp277
-rw-r--r--source/Commands/CommandObjectPlugin.cpp6
-rw-r--r--source/Commands/CommandObjectProcess.cpp6
-rw-r--r--source/Commands/CommandObjectTarget.cpp4
-rw-r--r--source/Commands/CommandObjectThread.cpp64
-rw-r--r--source/Commands/CommandObjectWatchpoint.cpp12
-rw-r--r--source/Core/Address.cpp12
-rw-r--r--source/Core/ConnectionFileDescriptor.cpp3
-rw-r--r--source/Core/Debugger.cpp53
-rw-r--r--source/Core/Mangled.cpp7
-rw-r--r--source/Core/Module.cpp2
-rw-r--r--source/Core/StreamFile.cpp2
-rw-r--r--source/Core/ValueObjectSyntheticFilter.cpp2
-rw-r--r--source/DataFormatters/CXXFormatterFunctions.cpp30
-rw-r--r--source/DataFormatters/FormatClasses.cpp13
-rw-r--r--source/DataFormatters/FormatManager.cpp133
-rw-r--r--source/DataFormatters/LibCxx.cpp8
-rw-r--r--source/DataFormatters/LibStdcpp.cpp16
-rw-r--r--source/DataFormatters/NSDictionary.cpp4
-rw-r--r--source/DataFormatters/NSSet.cpp70
-rw-r--r--source/DataFormatters/TypeCategory.cpp35
-rw-r--r--source/DataFormatters/TypeCategoryMap.cpp15
-rw-r--r--source/Expression/ClangFunction.cpp158
-rw-r--r--source/Expression/ClangUserExpression.cpp89
-rw-r--r--source/Expression/Materializer.cpp5
-rw-r--r--source/Host/common/File.cpp30
-rw-r--r--source/Host/common/FileSpec.cpp32
-rw-r--r--source/Host/common/Host.cpp192
-rw-r--r--source/Host/common/OptionParser.cpp58
-rw-r--r--source/Host/common/Symbols.cpp8
-rw-r--r--source/Interpreter/Args.cpp2
-rw-r--r--source/Interpreter/CommandInterpreter.cpp15
-rw-r--r--source/Interpreter/PythonDataObjects.cpp6
-rw-r--r--source/Interpreter/ScriptInterpreterPython.cpp7
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp76
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h7
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp116
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h7
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp90
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h7
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.h2
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp6
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h3
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp73
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h28
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp178
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h27
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp192
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h38
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp34
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h12
-rw-r--r--source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp2
-rw-r--r--source/Plugins/Process/POSIX/RegisterInfos_x86_64.h12
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.cpp95
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.h114
-rw-r--r--source/Plugins/Process/Utility/HistoryUnwind.cpp79
-rw-r--r--source/Plugins/Process/Utility/HistoryUnwind.h51
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp141
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.cpp138
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.h79
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp65
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp374
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h84
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp696
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h112
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp175
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h6
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp14
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h7
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp1
-rw-r--r--source/Symbol/UnwindPlan.cpp20
-rw-r--r--source/Target/Platform.cpp368
-rw-r--r--source/Target/Process.cpp106
-rw-r--r--source/Target/RegisterContext.cpp12
-rw-r--r--source/Target/StackFrameList.cpp19
-rw-r--r--source/Target/SystemRuntime.cpp10
-rw-r--r--source/Target/Target.cpp106
-rw-r--r--source/Target/Thread.cpp105
-rw-r--r--source/Target/ThreadPlanCallFunction.cpp167
-rw-r--r--source/Target/ThreadPlanCallUserExpression.cpp10
-rw-r--r--source/Target/ThreadPlanStepInRange.cpp4
-rw-r--r--source/Utility/StringExtractor.cpp7
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp28
-rw-r--r--source/Utility/StringExtractorGDBRemote.h26
-rw-r--r--source/lldb.cpp3
-rw-r--r--tools/lldb-platform/lldb-platform.cpp215
149 files changed, 6582 insertions, 2698 deletions
diff --git a/include/lldb/API/SBDebugger.h b/include/lldb/API/SBDebugger.h
index 518cbf67c932..80e6969cbd3a 100644
--- a/include/lldb/API/SBDebugger.h
+++ b/include/lldb/API/SBDebugger.h
@@ -10,9 +10,11 @@
#ifndef LLDB_SBDebugger_h_
#define LLDB_SBDebugger_h_
-#include "lldb/API/SBDefines.h"
#include <stdio.h>
+#include "lldb/API/SBDefines.h"
+#include "lldb/API/SBPlatform.h"
+
namespace lldb {
class SBDebugger
@@ -153,6 +155,12 @@ public:
void
SetSelectedTarget (SBTarget& target);
+ lldb::SBPlatform
+ GetSelectedPlatform();
+
+ void
+ SetSelectedPlatform(lldb::SBPlatform &platform);
+
lldb::SBSourceManager
GetSourceManager ();
diff --git a/include/lldb/API/SBError.h b/include/lldb/API/SBError.h
index a6d3dacb4549..12b34ec6dbc3 100644
--- a/include/lldb/API/SBError.h
+++ b/include/lldb/API/SBError.h
@@ -72,6 +72,7 @@ protected:
friend class SBCommunication;
friend class SBHostOS;
friend class SBInputReader;
+ friend class SBPlatform;
friend class SBProcess;
friend class SBThread;
friend class SBTarget;
diff --git a/include/lldb/API/SBExpressionOptions.h b/include/lldb/API/SBExpressionOptions.h
index eed9ed528bef..6a3a640432f6 100644
--- a/include/lldb/API/SBExpressionOptions.h
+++ b/include/lldb/API/SBExpressionOptions.h
@@ -65,6 +65,12 @@ public:
void
SetTryAllThreads (bool run_others = true);
+ bool
+ GetTrapExceptions () const;
+
+ void
+ SetTrapExceptions (bool trap_exceptions = true);
+
protected:
SBExpressionOptions (lldb_private::EvaluateExpressionOptions &expression_options);
diff --git a/include/lldb/API/SBFileSpec.h b/include/lldb/API/SBFileSpec.h
index e44abe4759c6..5d4447f74e64 100644
--- a/include/lldb/API/SBFileSpec.h
+++ b/include/lldb/API/SBFileSpec.h
@@ -45,6 +45,12 @@ public:
const char *
GetDirectory() const;
+ void
+ SetFilename(const char *filename);
+
+ void
+ SetDirectory(const char *directory);
+
uint32_t
GetPath (char *dst_path, size_t dst_len) const;
@@ -65,6 +71,7 @@ private:
friend class SBLineEntry;
friend class SBModule;
friend class SBModuleSpec;
+ friend class SBPlatform;
friend class SBProcess;
friend class SBSourceManager;
friend class SBThread;
diff --git a/include/lldb/API/SBModule.h b/include/lldb/API/SBModule.h
index a3c4879aa2f9..f5955b39734d 100644
--- a/include/lldb/API/SBModule.h
+++ b/include/lldb/API/SBModule.h
@@ -76,6 +76,42 @@ public:
bool
SetPlatformFileSpec (const lldb::SBFileSpec &platform_file);
+ //------------------------------------------------------------------
+ /// Get accessor for the remote install path for a module.
+ ///
+ /// When debugging to a remote platform by connecting to a remote
+ /// platform, the install path of the module can be set. If the
+ /// install path is set, every time the process is about to launch
+ /// the target will install this module on the remote platform prior
+ /// to launching.
+ ///
+ /// @return
+ /// A file specification object.
+ //------------------------------------------------------------------
+ lldb::SBFileSpec
+ GetRemoteInstallFileSpec ();
+
+ //------------------------------------------------------------------
+ /// Set accessor for the remote install path for a module.
+ ///
+ /// When debugging to a remote platform by connecting to a remote
+ /// platform, the install path of the module can be set. If the
+ /// install path is set, every time the process is about to launch
+ /// the target will install this module on the remote platform prior
+ /// to launching.
+ ///
+ /// If \a file specifies a full path to an install location, the
+ /// module will be installed to this path. If the path is relative
+ /// (no directory specified, or the path is partial like "usr/lib"
+ /// or "./usr/lib", then the install path will be resolved using
+ /// the platform's current working directory as the base path.
+ ///
+ /// @param[in]
+ /// A file specification object.
+ //------------------------------------------------------------------
+ bool
+ SetRemoteInstallFileSpec (lldb::SBFileSpec &file);
+
lldb::ByteOrder
GetByteOrder ();
diff --git a/include/lldb/API/SBPlatform.h b/include/lldb/API/SBPlatform.h
new file mode 100644
index 000000000000..16a546d81f9b
--- /dev/null
+++ b/include/lldb/API/SBPlatform.h
@@ -0,0 +1,198 @@
+//===-- SBPlatform.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SBPlatform_h_
+#define LLDB_SBPlatform_h_
+
+#include "lldb/API/SBDefines.h"
+
+struct PlatformConnectOptions;
+struct PlatformShellCommand;
+
+namespace lldb {
+
+ class SBPlatformConnectOptions
+ {
+ public:
+ SBPlatformConnectOptions (const char *url);
+
+ SBPlatformConnectOptions (const SBPlatformConnectOptions &rhs);
+
+ ~SBPlatformConnectOptions ();
+
+ void
+ operator=(const SBPlatformConnectOptions &rhs);
+
+ const char *
+ GetURL();
+
+ void
+ SetURL(const char *url);
+
+ bool
+ GetRsyncEnabled();
+
+ void
+ EnableRsync (const char *options,
+ const char *remote_path_prefix,
+ bool omit_remote_hostname);
+
+ void
+ DisableRsync ();
+
+ const char *
+ GetLocalCacheDirectory();
+
+ void
+ SetLocalCacheDirectory(const char *path);
+ protected:
+ PlatformConnectOptions *m_opaque_ptr;
+ };
+
+ class SBPlatformShellCommand
+ {
+ public:
+ SBPlatformShellCommand (const char *shell_command);
+
+ SBPlatformShellCommand (const SBPlatformShellCommand &rhs);
+
+ ~SBPlatformShellCommand();
+
+ void
+ Clear();
+
+ const char *
+ GetCommand();
+
+ void
+ SetCommand(const char *shell_command);
+
+ const char *
+ GetWorkingDirectory ();
+
+ void
+ SetWorkingDirectory (const char *path);
+
+ uint32_t
+ GetTimeoutSeconds ();
+
+ void
+ SetTimeoutSeconds (uint32_t sec);
+
+ int
+ GetSignal ();
+
+ int
+ GetStatus ();
+
+ const char *
+ GetOutput ();
+
+ protected:
+ friend class SBPlatform;
+
+ PlatformShellCommand *m_opaque_ptr;
+ };
+
+ class SBPlatform
+ {
+ public:
+
+ SBPlatform ();
+
+ SBPlatform (const char *platform_name);
+
+ ~SBPlatform();
+
+ bool
+ IsValid () const;
+
+ void
+ Clear ();
+
+ const char *
+ GetWorkingDirectory();
+
+ bool
+ SetWorkingDirectory(const char *path);
+
+ const char *
+ GetName ();
+
+ SBError
+ ConnectRemote (SBPlatformConnectOptions &connect_options);
+
+ void
+ DisconnectRemote ();
+
+ bool
+ IsConnected();
+
+ //----------------------------------------------------------------------
+ // The following functions will work if the platform is connected
+ //----------------------------------------------------------------------
+ const char *
+ GetTriple();
+
+ const char *
+ GetHostname ();
+
+ const char *
+ GetOSBuild ();
+
+ const char *
+ GetOSDescription ();
+
+ uint32_t
+ GetOSMajorVersion ();
+
+ uint32_t
+ GetOSMinorVersion ();
+
+ uint32_t
+ GetOSUpdateVersion ();
+
+ SBError
+ Put (SBFileSpec &src, SBFileSpec &dst);
+
+ SBError
+ Get (SBFileSpec &src, SBFileSpec &dst);
+
+ SBError
+ Install (SBFileSpec& src, SBFileSpec& dst);
+
+ SBError
+ Run (SBPlatformShellCommand &shell_command);
+
+ SBError
+ MakeDirectory (const char *path, uint32_t file_permissions = eFilePermissionsDirectoryDefault);
+
+ uint32_t
+ GetFilePermissions (const char *path);
+
+ SBError
+ SetFilePermissions (const char *path, uint32_t file_permissions);
+
+ protected:
+
+ friend class SBDebugger;
+ friend class SBTarget;
+
+ lldb::PlatformSP
+ GetSP () const;
+
+ void
+ SetSP (const lldb::PlatformSP& platform_sp);
+
+ lldb::PlatformSP m_opaque_sp;
+ };
+
+} // namespace lldb
+
+#endif // LLDB_SBPlatform_h_
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index 7bcf91c16d77..b41c11811549 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -268,6 +268,23 @@ public:
GetProcess ();
//------------------------------------------------------------------
+ /// Install any binaries that need to be installed.
+ ///
+ /// This function does nothing when debugging on the host system.
+ /// When connected to remote platforms, the target's main executable
+ /// and any modules that have their remote install path set will be
+ /// installed on the remote platform. If the main executable doesn't
+ /// have an install location set, it will be installed in the remote
+ /// platform's working directory.
+ ///
+ /// @return
+ /// An error describing anything that went wrong during
+ /// installation.
+ //------------------------------------------------------------------
+ SBError
+ Install();
+
+ //------------------------------------------------------------------
/// Launch a new process.
///
/// Launch a new process by spawning a new process using the
diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h
index d062d7121303..6542dca1f95a 100644
--- a/include/lldb/API/SBThread.h
+++ b/include/lldb/API/SBThread.h
@@ -202,7 +202,10 @@ public:
GetStatus (lldb::SBStream &status) const;
SBThread
- GetExtendedBacktrace (const char *type);
+ GetExtendedBacktraceThread (const char *type);
+
+ uint32_t
+ GetExtendedBacktraceOriginatingIndexID ();
protected:
friend class SBBreakpoint;
diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h
index 30cc3314af3a..e82d6eacf7a8 100644
--- a/include/lldb/Breakpoint/Breakpoint.h
+++ b/include/lldb/Breakpoint/Breakpoint.h
@@ -311,6 +311,24 @@ public:
//------------------------------------------------------------------
lldb::BreakpointLocationSP
GetLocationAtIndex (size_t index);
+
+ //------------------------------------------------------------------
+ /// Removes all invalid breakpoint locations.
+ ///
+ /// Removes all breakpoint locations with architectures that aren't
+ /// compatible with \a arch. Also remove any breakpoint locations
+ /// with whose locations have address where the section has been
+ /// deleted (module and object files no longer exist).
+ ///
+ /// This is typically used after the process calls exec, or anytime
+ /// the architecture of the target changes.
+ ///
+ /// @param[in] arch
+ /// If valid, check the module in each breakpoint to make sure
+ /// they are compatible, otherwise, ignore architecture.
+ //------------------------------------------------------------------
+ void
+ RemoveInvalidLocations (const ArchSpec &arch);
//------------------------------------------------------------------
// The next section deals with various breakpoint options.
diff --git a/include/lldb/Breakpoint/BreakpointList.h b/include/lldb/Breakpoint/BreakpointList.h
index c6708db118df..27f80d0ffe09 100644
--- a/include/lldb/Breakpoint/BreakpointList.h
+++ b/include/lldb/Breakpoint/BreakpointList.h
@@ -132,6 +132,25 @@ public:
bool
Remove (lldb::break_id_t breakID, bool notify);
+
+ //------------------------------------------------------------------
+ /// Removes all invalid breakpoint locations.
+ ///
+ /// Removes all breakpoint locations in the list with architectures
+ /// that aren't compatible with \a arch. Also remove any breakpoint
+ /// locations with whose locations have address where the section
+ /// has been deleted (module and object files no longer exist).
+ ///
+ /// This is typically used after the process calls exec, or anytime
+ /// the architecture of the target changes.
+ ///
+ /// @param[in] arch
+ /// If valid, check the module in each breakpoint to make sure
+ /// they are compatible, otherwise, ignore architecture.
+ //------------------------------------------------------------------
+ void
+ RemoveInvalidLocations (const ArchSpec &arch);
+
void
SetEnabledAll (bool enabled);
diff --git a/include/lldb/Breakpoint/BreakpointLocationList.h b/include/lldb/Breakpoint/BreakpointLocationList.h
index 1cba23d9118e..b25208659c7f 100644
--- a/include/lldb/Breakpoint/BreakpointLocationList.h
+++ b/include/lldb/Breakpoint/BreakpointLocationList.h
@@ -250,6 +250,9 @@ protected:
bool
RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp);
+
+ void
+ RemoveInvalidLocations (const ArchSpec &arch);
typedef std::vector<lldb::BreakpointLocationSP> collection;
typedef std::map<lldb_private::Address,
@@ -257,7 +260,7 @@ protected:
Address::ModulePointerAndOffsetLessThanFunctionObject> addr_map;
Breakpoint &m_owner;
- collection m_locations;
+ collection m_locations; // Vector of locations, sorted by ID
addr_map m_address_to_location;
mutable Mutex m_mutex;
lldb::break_id_t m_next_id;
diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h
index da7cc5c03d38..322019395ae7 100644
--- a/include/lldb/Core/Address.h
+++ b/include/lldb/Core/Address.h
@@ -534,6 +534,16 @@ public:
bool
CalculateSymbolContextLineEntry (LineEntry &line_entry) const;
+ //------------------------------------------------------------------
+ // Returns true if the section should be valid, but isn't because
+ // the shared pointer to the section can't be reconstructed from
+ // a weak pointer that contains a valid weak reference to a section.
+ // Returns false if the section weak pointer has no reference to
+ // a section, or if the section is still valid
+ //------------------------------------------------------------------
+ bool
+ SectionWasDeleted() const;
+
protected:
//------------------------------------------------------------------
// Member variables.
@@ -550,7 +560,7 @@ protected:
// have a valid section.
//------------------------------------------------------------------
bool
- SectionWasDeleted() const;
+ SectionWasDeletedPrivate() const;
};
diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h
index 671b378df807..a3c6d5eeb93d 100644
--- a/include/lldb/Core/Debugger.h
+++ b/include/lldb/Core/Debugger.h
@@ -17,9 +17,6 @@
#include <stack>
#include "lldb/lldb-public.h"
-
-#include "lldb/API/SBDefines.h"
-
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/InputReaderStack.h"
@@ -55,6 +52,10 @@ friend class SourceManager; // For GetSourceFileCache.
public:
+ typedef lldb::DynamicLibrarySP (*LoadPluginCallbackType) (const lldb::DebuggerSP &debugger_sp,
+ const FileSpec& spec,
+ Error& error);
+
static lldb::DebuggerSP
CreateInstance (lldb::LogOutputCallback log_callback = NULL, void *baton = NULL);
@@ -65,7 +66,7 @@ public:
FindTargetWithProcess (Process *process);
static void
- Initialize ();
+ Initialize (LoadPluginCallbackType load_plugin_callback);
static void
Terminate ();
@@ -333,9 +334,7 @@ public:
{
return m_instance_name;
}
-
- typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger);
-
+
bool
LoadPlugin (const FileSpec& spec, Error& error);
@@ -377,6 +376,7 @@ protected:
LogStreamMap m_log_streams;
lldb::StreamSP m_log_callback_stream_sp;
ConstString m_instance_name;
+ static LoadPluginCallbackType g_load_plugin_callback;
typedef std::vector<lldb::DynamicLibrarySP> LoadedPluginsList;
LoadedPluginsList m_loaded_plugins;
diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h
index 1473fb90cf85..cae5a30be704 100644
--- a/include/lldb/Core/Module.h
+++ b/include/lldb/Core/Module.h
@@ -570,6 +570,18 @@ public:
}
const FileSpec &
+ GetRemoteInstallFileSpec () const
+ {
+ return m_remote_install_file;
+ }
+
+ void
+ SetRemoteInstallFileSpec (const FileSpec &file)
+ {
+ m_remote_install_file = file;
+ }
+
+ const FileSpec &
GetSymbolFileFileSpec () const
{
return m_symfile_spec;
@@ -1059,6 +1071,7 @@ protected:
lldb_private::UUID m_uuid; ///< Each module is assumed to have a unique identifier to help match it up to debug symbols.
FileSpec m_file; ///< The file representation on disk for this module (if there is one).
FileSpec m_platform_file;///< The path to the module on the platform on which it is being debugged
+ FileSpec m_remote_install_file; ///< If set when debugging on remote platforms, this module will be installed at this location
FileSpec m_symfile_spec; ///< If this path is valid, then this is the file that _will_ be used as the symbol file for this module
ConstString m_object_name; ///< The name an object within this module that is selected, or empty of the module is represented by \a m_file.
uint64_t m_object_offset;
diff --git a/include/lldb/DataFormatters/CXXFormatterFunctions.h b/include/lldb/DataFormatters/CXXFormatterFunctions.h
index 433c2a3c407b..415ef9be59ef 100644
--- a/include/lldb/DataFormatters/CXXFormatterFunctions.h
+++ b/include/lldb/DataFormatters/CXXFormatterFunctions.h
@@ -17,6 +17,8 @@
#include "lldb/Core/ConstString.h"
#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "clang/AST/ASTContext.h"
diff --git a/include/lldb/DataFormatters/FormatCache.h b/include/lldb/DataFormatters/FormatCache.h
index bd9e20ccc9ee..1505d7c46189 100644
--- a/include/lldb/DataFormatters/FormatCache.h
+++ b/include/lldb/DataFormatters/FormatCache.h
@@ -18,6 +18,7 @@
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/ConstString.h"
+#include "lldb/Host/Mutex.h"
#include "lldb/DataFormatters/FormatClasses.h"
namespace lldb_private {
diff --git a/include/lldb/DataFormatters/FormatClasses.h b/include/lldb/DataFormatters/FormatClasses.h
index 6d9a50e8f2c5..651160371c69 100644
--- a/include/lldb/DataFormatters/FormatClasses.h
+++ b/include/lldb/DataFormatters/FormatClasses.h
@@ -10,9 +10,6 @@
#ifndef lldb_FormatClasses_h_
#define lldb_FormatClasses_h_
-// C Includes
-#include <stdint.h>
-
// C++ Includes
#include <string>
#include <vector>
@@ -23,17 +20,86 @@
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/Type.h"
-#include "lldb/DataFormatters/TypeFormat.h"
-#include "lldb/DataFormatters/TypeSummary.h"
-#include "lldb/DataFormatters/TypeSynthetic.h"
-
namespace lldb_private {
+class FormattersMatchCandidate
+{
+public:
+
+ FormattersMatchCandidate (ConstString name,
+ uint32_t reason,
+ bool strip_ptr,
+ bool strip_ref,
+ bool strip_tydef) :
+ m_type_name(name),
+ m_reason(reason),
+ m_stripped_pointer(strip_ptr),
+ m_stripped_reference(strip_ref),
+ m_stripped_typedef(strip_tydef)
+ {
+ }
+
+ ~FormattersMatchCandidate ()
+ {}
+
+ ConstString
+ GetTypeName () const
+ {
+ return m_type_name;
+ }
+
+ uint32_t
+ GetReason () const
+ {
+ return m_reason;
+ }
+
+ bool
+ DidStripPointer () const
+ {
+ return m_stripped_pointer;
+ }
+
+ bool
+ DidStripReference () const
+ {
+ return m_stripped_reference;
+ }
+
+ bool
+ DidStripTypedef () const
+ {
+ return m_stripped_typedef;
+ }
+
+ template <class Formatter>
+ bool
+ IsMatch (const std::shared_ptr<Formatter>& formatter_sp) const
+ {
+ if (!formatter_sp)
+ return false;
+ if (formatter_sp->Cascades() == false && DidStripTypedef())
+ return false;
+ if (formatter_sp->SkipsPointers() && DidStripPointer())
+ return false;
+ if (formatter_sp->SkipsReferences() && DidStripReference())
+ return false;
+ return true;
+ }
+
+private:
+ ConstString m_type_name;
+ uint32_t m_reason;
+ bool m_stripped_pointer;
+ bool m_stripped_reference;
+ bool m_stripped_typedef;
+};
+
+typedef std::vector<FormattersMatchCandidate> FormattersMatchVector;
+
class TypeNameSpecifierImpl
{
public:
diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h
index 3c90c993e0c4..750e53008318 100644
--- a/include/lldb/DataFormatters/FormatManager.h
+++ b/include/lldb/DataFormatters/FormatManager.h
@@ -19,6 +19,7 @@
#include "lldb/lldb-enumerations.h"
#include "lldb/DataFormatters/FormatCache.h"
+#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/FormatNavigator.h"
#include "lldb/DataFormatters/TypeCategory.h"
#include "lldb/DataFormatters/TypeCategoryMap.h"
@@ -213,7 +214,36 @@ public:
{
}
+ static FormattersMatchVector
+ GetPossibleMatches (ValueObject& valobj,
+ lldb::DynamicValueType use_dynamic)
+ {
+ FormattersMatchVector matches;
+ GetPossibleMatches (valobj,
+ valobj.GetClangType(),
+ lldb_private::eFormatterChoiceCriterionDirectChoice,
+ use_dynamic,
+ matches,
+ false,
+ false,
+ false,
+ true);
+ return matches;
+ }
+
private:
+
+ static void
+ GetPossibleMatches (ValueObject& valobj,
+ ClangASTType clang_type,
+ uint32_t reason,
+ lldb::DynamicValueType use_dynamic,
+ FormattersMatchVector& entries,
+ bool did_strip_ptr,
+ bool did_strip_ref,
+ bool did_strip_typedef,
+ bool root_level = false);
+
FormatCache m_format_cache;
NamedSummariesMap m_named_summaries_map;
std::atomic<uint32_t> m_last_revision;
diff --git a/include/lldb/DataFormatters/FormatNavigator.h b/include/lldb/DataFormatters/FormatNavigator.h
index cd5f6824e199..1b82776fb28c 100644
--- a/include/lldb/DataFormatters/FormatNavigator.h
+++ b/include/lldb/DataFormatters/FormatNavigator.h
@@ -26,6 +26,9 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/TypeFormat.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTType.h"
@@ -459,228 +462,29 @@ protected:
}
return false;
}
-
- bool
- Get_BitfieldMatch (ValueObject& valobj,
- ConstString typeName,
- MapValueType& entry,
- uint32_t& reason)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- // for bitfields, append size to the typename so one can custom format them
- StreamString sstring;
- sstring.Printf("%s:%d",typeName.AsCString(),valobj.GetBitfieldBitSize());
- ConstString bitfieldname = ConstString(sstring.GetData());
- if (log)
- log->Printf("[Get_BitfieldMatch] appended bitfield info, final result is %s", bitfieldname.GetCString());
- if (Get(bitfieldname, entry))
- {
- if (log)
- log->Printf("[Get_BitfieldMatch] bitfield direct match found, returning");
- return true;
- }
- else
- {
- reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
- if (log)
- log->Printf("[Get_BitfieldMatch] no bitfield direct match");
- return false;
- }
- }
-
- bool Get_ObjC (ValueObject& valobj,
- MapValueType& entry)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
- lldb::ProcessSP process_sp = valobj.GetProcessSP();
- ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
- if (runtime == NULL)
- {
- if (log)
- log->Printf("[Get_ObjC] no valid ObjC runtime, skipping dynamic");
- return false;
- }
- ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
- if (!objc_class_sp)
- {
- if (log)
- log->Printf("[Get_ObjC] invalid ISA, skipping dynamic");
- return false;
- }
- ConstString name (objc_class_sp->GetClassName());
- if (log)
- log->Printf("[Get_ObjC] dynamic type inferred is %s - looking for direct dynamic match", name.GetCString());
- if (Get(name, entry))
- {
- if (log)
- log->Printf("[Get_ObjC] direct dynamic match found, returning");
- return true;
- }
- if (log)
- log->Printf("[Get_ObjC] no dynamic match");
- return false;
- }
-
+
bool
- Get_Impl (ValueObject& valobj,
- ClangASTType clang_type,
- MapValueType& entry,
- lldb::DynamicValueType use_dynamic,
- uint32_t& reason)
+ Get (const FormattersMatchVector& candidates,
+ MapValueType& entry,
+ uint32_t *reason)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
- if (!clang_type.IsValid())
- {
- if (log)
- log->Printf("[Get_Impl] type is invalid, returning");
- return false;
- }
-
- clang_type = clang_type.RemoveFastQualifiers();
-
- ConstString typeName(clang_type.GetConstTypeName());
-
- if (valobj.GetBitfieldBitSize() > 0)
+ for (const FormattersMatchCandidate& candidate : candidates)
{
- if (Get_BitfieldMatch(valobj, typeName, entry, reason))
- return true;
- }
-
- if (log)
- log->Printf("[Get_Impl] trying to get %s for VO name %s of type %s",
- m_name.c_str(),
- valobj.GetName().AsCString(),
- typeName.AsCString());
-
- if (Get(typeName, entry))
- {
- if (log)
- log->Printf("[Get] direct match found, returning");
- return true;
- }
- if (log)
- log->Printf("[Get_Impl] no direct match");
-
- // strip pointers and references and see if that helps
- if (clang_type.IsReferenceType())
- {
- if (log)
- log->Printf("[Get_Impl] stripping reference");
- if (Get_Impl(valobj, clang_type.GetNonReferenceType(), entry, use_dynamic, reason) && !entry->SkipsReferences())
+ if (Get(candidate.GetTypeName(),entry))
{
- reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
- return true;
- }
- }
- else if (clang_type.IsPointerType())
- {
- if (log)
- log->Printf("[Get_Impl] stripping pointer");
- if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
- {
- reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
- return true;
- }
- }
-
- bool canBeObjCDynamic = valobj.GetClangType().IsPossibleDynamicType (NULL,
- false, // no C++
- true); // yes ObjC
-
- if (canBeObjCDynamic)
- {
- if (use_dynamic != lldb::eNoDynamicValues)
- {
- if (log)
- log->Printf("[Get_Impl] allowed to figure out dynamic ObjC type");
- if (Get_ObjC(valobj,entry))
+ if (candidate.IsMatch(entry) == false)
{
- reason |= lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery;
- return true;
+ entry.reset();
+ continue;
}
- }
- if (log)
- log->Printf("[Get_Impl] dynamic disabled or failed - stripping ObjC pointer");
- if (Get_Impl(valobj, clang_type.GetPointeeType(), entry, use_dynamic, reason) && !entry->SkipsPointers())
- {
- reason |= lldb_private::eFormatterChoiceCriterionStrippedPointerReference;
- return true;
- }
- }
-
- // try to strip typedef chains
- if (clang_type.IsTypedefType())
- {
- if (log)
- log->Printf("[Get_Impl] stripping typedef");
- if ((Get_Impl(valobj, clang_type.GetTypedefedType(), entry, use_dynamic, reason)) && entry->Cascades())
- {
- reason |= lldb_private::eFormatterChoiceCriterionNavigatedTypedefs;
- return true;
- }
- }
-
- // out of luck here
- return false;
- }
-
- // we are separately passing in valobj and type because the valobj is fixed (and is used for ObjC discovery and bitfield size)
- // but the type can change (e.g. stripping pointers, ...)
- bool Get (ValueObject& valobj,
- ClangASTType clang_type,
- MapValueType& entry,
- lldb::DynamicValueType use_dynamic,
- uint32_t& reason)
- {
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
-
- if (Get_Impl (valobj, clang_type, entry, use_dynamic, reason))
- return true;
-
- // try going to the unqualified type
- do {
- if (log)
- log->Printf("[Get] trying the unqualified type");
- if (!clang_type.IsValid())
- break;
-
- ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
- if (!unqual_clang_ast_type.IsValid())
- {
- if (log)
- log->Printf("[Get] could not get the unqual_clang_ast_type");
- break;
- }
- if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
- {
- if (log)
- log->Printf("[Get] unqualified type is there and is not the same, let's try");
- if (Get_Impl (valobj, unqual_clang_ast_type,entry, use_dynamic, reason))
- return true;
- }
- else if (log)
- log->Printf("[Get] unqualified type same as original type");
- } while(false);
-
- // if all else fails, go to static type
- if (valobj.IsDynamic())
- {
- if (log)
- log->Printf("[Get] going to static value");
- lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
- if (static_value_sp)
- {
- if (log)
- log->Printf("[Get] has a static value - actually use it");
- if (Get(*static_value_sp.get(), static_value_sp->GetClangType(), entry, use_dynamic, reason))
+ else
{
- reason |= lldb_private::eFormatterChoiceCriterionWentToStaticValue;
+ if(reason)
+ *reason = candidate.GetReason();
return true;
}
}
}
-
return false;
}
};
diff --git a/include/lldb/DataFormatters/TypeCategory.h b/include/lldb/DataFormatters/TypeCategory.h
index 6461c4e97e4e..082395a04616 100644
--- a/include/lldb/DataFormatters/TypeCategory.h
+++ b/include/lldb/DataFormatters/TypeCategory.h
@@ -18,6 +18,7 @@
#include "lldb/lldb-public.h"
#include "lldb/lldb-enumerations.h"
+#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/FormatNavigator.h"
namespace lldb_private {
@@ -177,23 +178,22 @@ namespace lldb_private {
return m_enabled_position;
}
-
bool
Get (ValueObject& valobj,
+ const FormattersMatchVector& candidates,
lldb::TypeFormatImplSP& entry,
- lldb::DynamicValueType use_dynamic,
uint32_t* reason = NULL);
bool
Get (ValueObject& valobj,
+ const FormattersMatchVector& candidates,
lldb::TypeSummaryImplSP& entry,
- lldb::DynamicValueType use_dynamic,
uint32_t* reason = NULL);
bool
Get (ValueObject& valobj,
+ const FormattersMatchVector& candidates,
lldb::SyntheticChildrenSP& entry,
- lldb::DynamicValueType use_dynamic,
uint32_t* reason = NULL);
void
diff --git a/include/lldb/Expression/ClangFunction.h b/include/lldb/Expression/ClangFunction.h
index 9cb22ed15cb5..9c14ddb53230 100644
--- a/include/lldb/Expression/ClangFunction.h
+++ b/include/lldb/Expression/ClangFunction.h
@@ -227,143 +227,6 @@ public:
Stream &errors);
//------------------------------------------------------------------
- /// [Static] Execute a function, passing it a single void* parameter.
- /// ClangFunction uses this to call the wrapper function.
- ///
- /// @param[in] exe_ctx
- /// The execution context to insert the function and its arguments
- /// into.
- ///
- /// @param[in] function_address
- /// The address of the function in the target process.
- ///
- /// @param[in] void_arg
- /// The value of the void* parameter.
- ///
- /// @param[in] stop_others
- /// True if other threads should pause during execution.
- ///
- /// @param[in] try_all_threads
- /// If the timeout expires, true if other threads should run. If
- /// the function may try to take locks, this is useful.
- ///
- /// @param[in] unwind_on_error
- /// If true, and the execution stops before completion, we unwind the
- /// function call, and return the program state to what it was before the
- /// execution. If false, we leave the program in the stopped state.
- ///
- /// @param[in] timeout_usec
- /// Timeout value (0 for no timeout). If try_all_threads is true, then we
- /// will try on one thread for the lesser of .25 sec and half the total timeout.
- /// then switch to running all threads, otherwise this will be the total timeout.
- ///
- /// @param[in] errors
- /// The stream to write errors to.
- ///
- /// @param[in] this_arg
- /// If non-NULL, the function is invoked like a C++ method, with the
- /// value pointed to by the pointer as its 'this' argument.
- ///
- /// @return
- /// Returns one of the ExecutionResults enum indicating function call status.
- //------------------------------------------------------------------
- static ExecutionResults
- ExecuteFunction (ExecutionContext &exe_ctx,
- lldb::addr_t function_address,
- lldb::addr_t &void_arg,
- bool stop_others,
- bool try_all_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- uint32_t timeout_usec,
- Stream &errors,
- lldb::addr_t* this_arg = 0);
-
- //------------------------------------------------------------------
- /// Run the function this ClangFunction was created with.
- ///
- /// This simple version will run the function stopping other threads
- /// for a fixed timeout period (1000 usec) and if it does not complete,
- /// we halt the process and try with all threads running.
- ///
- /// @param[in] exe_ctx
- /// The thread & process in which this function will run.
- ///
- /// @param[in] errors
- /// Errors will be written here if there are any.
- ///
- /// @param[out] results
- /// The result value will be put here after running the function.
- ///
- /// @return
- /// Returns one of the ExecutionResults enum indicating function call status.
- //------------------------------------------------------------------
- ExecutionResults
- ExecuteFunction(ExecutionContext &exe_ctx,
- Stream &errors,
- Value &results);
-
- //------------------------------------------------------------------
- /// Run the function this ClangFunction was created with.
- ///
- /// This simple version will run the function obeying the stop_others
- /// argument. There is no timeout.
- ///
- /// @param[in] exe_ctx
- /// The thread & process in which this function will run.
- ///
- /// @param[in] errors
- /// Errors will be written here if there are any.
- ///
- /// @param[in] stop_others
- /// If \b true, run only this thread, if \b false let all threads run.
- ///
- /// @param[out] results
- /// The result value will be put here after running the function.
- ///
- /// @return
- /// Returns one of the ExecutionResults enum indicating function call status.
- //------------------------------------------------------------------
- ExecutionResults
- ExecuteFunction(ExecutionContext &exe_ctx,
- Stream &errors, bool stop_others,
- Value &results);
-
- //------------------------------------------------------------------
- /// Run the function this ClangFunction was created with.
- ///
- /// This simple version will run the function on one thread. If \a timeout_usec
- /// is not zero, we time out after that timeout. If \a try_all_threads is true, then we will
- /// resume with all threads on, otherwise we halt the process, and eExecutionInterrupted will be returned.
- ///
- /// @param[in] exe_ctx
- /// The thread & process in which this function will run.
- ///
- /// @param[in] errors
- /// Errors will be written here if there are any.
- ///
- /// @param[in] timeout_usec
- /// Timeout value (0 for no timeout). If try_all_threads is true, then we
- /// will try on one thread for the lesser of .25 sec and half the total timeout.
- /// then switch to running all threads, otherwise this will be the total timeout.
- ///
- /// @param[in] try_all_threads
- /// If \b true, run only this thread, if \b false let all threads run.
- ///
- /// @param[out] results
- /// The result value will be put here after running the function.
- ///
- /// @return
- /// Returns one of the ExecutionResults enum indicating function call status.
- //------------------------------------------------------------------
- ExecutionResults
- ExecuteFunction(ExecutionContext &exe_ctx,
- Stream &errors,
- uint32_t single_thread_timeout_usec,
- bool try_all_threads,
- Value &results);
-
- //------------------------------------------------------------------
/// Run the function this ClangFunction was created with.
///
/// This is the full version.
@@ -381,17 +244,8 @@ public:
/// @param[in] errors
/// Errors will be written here if there are any.
///
- /// @param[in] stop_others
- /// If \b true, run only this thread, if \b false let all threads run.
- ///
- /// @param[in] timeout_usec
- /// Timeout value (0 for no timeout). If try_all_threads is true, then we
- /// will try on one thread for the lesser of .25 sec and half the total timeout.
- /// then switch to running all threads, otherwise this will be the total timeout.
- ///
- ///
- /// @param[in] try_all_threads
- /// If \b true, run only this thread, if \b false let all threads run.
+ /// @param[in] options
+ /// The options for this expression execution.
///
/// @param[out] results
/// The result value will be put here after running the function.
@@ -402,63 +256,11 @@ public:
ExecutionResults
ExecuteFunction(ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
- Stream &errors,
- bool stop_others,
- uint32_t timeout_usec,
- bool try_all_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
+ const EvaluateExpressionOptions &options,
+ Stream &errors,
Value &results);
//------------------------------------------------------------------
- /// [static] Get a thread plan to run a function.
- ///
- /// @param[in] exe_ctx
- /// The execution context to insert the function and its arguments
- /// into.
- ///
- /// @param[in] func_addr
- /// The address of the function in the target process.
- ///
- /// @param[in] args_addr_ref
- /// The value of the void* parameter.
- ///
- /// @param[in] errors
- /// The stream to write errors to.
- ///
- /// @param[in] stop_others
- /// True if other threads should pause during execution.
- ///
- /// @param[in] unwind_on_error
- /// True if the thread plan may simply be discarded if an error occurs.
- ///
- /// @param[in] ignore_breakpoints
- /// True if the expression execution will ignore breakpoint hits and continue executing.
- ///
- /// @param[in] this_arg
- /// If non-NULL (and cmd_arg is NULL), the function is invoked like a C++
- /// method, with the value pointed to by the pointer as its 'this'
- /// argument.
- ///
- /// @param[in] cmd_arg
- /// If non-NULL, the function is invoked like an Objective-C method, with
- /// this_arg in the 'self' slot and cmd_arg in the '_cmd' slot
- ///
- /// @return
- /// A ThreadPlan for executing the function.
- //------------------------------------------------------------------
- static ThreadPlan *
- GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
- lldb::addr_t func_addr,
- lldb::addr_t &args_addr_ref,
- Stream &errors,
- bool stop_others,
- bool unwind_on_error,
- bool ignore_breakpoints,
- lldb::addr_t *this_arg = 0,
- lldb::addr_t *cmd_arg = 0);
-
- //------------------------------------------------------------------
/// Get a thread plan to run the function this ClangFunction was created with.
///
/// @param[in] exe_ctx
@@ -468,8 +270,8 @@ public:
/// @param[in] func_addr
/// The address of the function in the target process.
///
- /// @param[in] args_addr_ref
- /// The value of the void* parameter.
+ /// @param[in] args_addr
+ /// The address of the argument struct.
///
/// @param[in] errors
/// The stream to write errors to.
@@ -485,20 +287,9 @@ public:
//------------------------------------------------------------------
ThreadPlan *
GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
- lldb::addr_t &args_addr_ref,
- Stream &errors,
- bool stop_others,
- bool unwind_on_error = true,
- bool ignore_breakpoints = true)
- {
- return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
- m_jit_start_addr,
- args_addr_ref,
- errors,
- stop_others,
- unwind_on_error,
- ignore_breakpoints);
- }
+ lldb::addr_t args_addr,
+ const EvaluateExpressionOptions &options,
+ Stream &errors);
//------------------------------------------------------------------
/// Get the result of the function from its struct
diff --git a/include/lldb/Expression/ClangUserExpression.h b/include/lldb/Expression/ClangUserExpression.h
index b8c3c128acf4..83fdf1c21955 100644
--- a/include/lldb/Expression/ClangUserExpression.h
+++ b/include/lldb/Expression/ClangUserExpression.h
@@ -150,10 +150,6 @@ public:
ClangUserExpressionSP &shared_ptr_to_me,
lldb::ClangExpressionVariableSP &result);
- ThreadPlan *
- GetThreadPlanToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx);
-
//------------------------------------------------------------------
/// Apply the side effects of the function to program state.
///
diff --git a/include/lldb/Host/Debug.h b/include/lldb/Host/Debug.h
new file mode 100644
index 000000000000..2cb758e1b733
--- /dev/null
+++ b/include/lldb/Host/Debug.h
@@ -0,0 +1,406 @@
+//===-- Debug.h -------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Debug_h_
+#define liblldb_Debug_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Mutex.h"
+#include <vector>
+
+namespace lldb_private {
+
+ //------------------------------------------------------------------
+ // Tells a thread what it needs to do when the process is resumed.
+ //------------------------------------------------------------------
+ struct ResumeAction
+ {
+ lldb::tid_t tid; // The thread ID that this action applies to, LLDB_INVALID_THREAD_ID for the default thread action
+ lldb::StateType state; // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping.
+ int signal; // When resuming this thread, resume it with this signal if this value is > 0
+ };
+
+ //------------------------------------------------------------------
+ // A class that contains instructions for all threads for
+ // NativeProcessProtocol::Resume(). Each thread can either run, stay
+ // suspended, or step when the process is resumed. We optionally
+ // have the ability to also send a signal to the thread when the
+ // action is run or step.
+ //------------------------------------------------------------------
+ class ResumeActionList
+ {
+ public:
+ ResumeActionList () :
+ m_actions (),
+ m_signal_handled ()
+ {
+ }
+
+ ResumeActionList (lldb::StateType default_action, int signal) :
+ m_actions(),
+ m_signal_handled ()
+ {
+ SetDefaultThreadActionIfNeeded (default_action, signal);
+ }
+
+
+ ResumeActionList (const ResumeAction *actions, size_t num_actions) :
+ m_actions (),
+ m_signal_handled ()
+ {
+ if (actions && num_actions)
+ {
+ m_actions.assign (actions, actions + num_actions);
+ m_signal_handled.assign (num_actions, false);
+ }
+ }
+
+ ~ResumeActionList()
+ {
+ }
+
+ bool
+ IsEmpty() const
+ {
+ return m_actions.empty();
+ }
+
+ void
+ Append (const ResumeAction &action)
+ {
+ m_actions.push_back (action);
+ m_signal_handled.push_back (false);
+ }
+
+ void
+ AppendAction (lldb::tid_t tid,
+ lldb::StateType state,
+ int signal = 0)
+ {
+ ResumeAction action = { tid, state, signal };
+ Append (action);
+ }
+
+ void
+ AppendResumeAll ()
+ {
+ AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
+ }
+
+ void
+ AppendSuspendAll ()
+ {
+ AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
+ }
+
+ void
+ AppendStepAll ()
+ {
+ AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
+ }
+
+ const ResumeAction *
+ GetActionForThread (lldb::tid_t tid, bool default_ok) const
+ {
+ const size_t num_actions = m_actions.size();
+ for (size_t i=0; i<num_actions; ++i)
+ {
+ if (m_actions[i].tid == tid)
+ return &m_actions[i];
+ }
+ if (default_ok && tid != LLDB_INVALID_THREAD_ID)
+ return GetActionForThread (LLDB_INVALID_THREAD_ID, false);
+ return NULL;
+ }
+
+ size_t
+ NumActionsWithState (lldb::StateType state) const
+ {
+ size_t count = 0;
+ const size_t num_actions = m_actions.size();
+ for (size_t i=0; i<num_actions; ++i)
+ {
+ if (m_actions[i].state == state)
+ ++count;
+ }
+ return count;
+ }
+
+ bool
+ SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal)
+ {
+ if (GetActionForThread (LLDB_INVALID_THREAD_ID, true) == NULL)
+ {
+ // There isn't a default action so we do need to set it.
+ ResumeAction default_action = {LLDB_INVALID_THREAD_ID, action, signal };
+ m_actions.push_back (default_action);
+ m_signal_handled.push_back (false);
+ return true; // Return true as we did add the default action
+ }
+ return false;
+ }
+
+ void
+ SetSignalHandledForThread (lldb::tid_t tid) const
+ {
+ if (tid != LLDB_INVALID_THREAD_ID)
+ {
+ const size_t num_actions = m_actions.size();
+ for (size_t i=0; i<num_actions; ++i)
+ {
+ if (m_actions[i].tid == tid)
+ m_signal_handled[i] = true;
+ }
+ }
+ }
+
+ const ResumeAction *
+ GetFirst() const
+ {
+ return m_actions.data();
+ }
+
+ size_t
+ GetSize () const
+ {
+ return m_actions.size();
+ }
+
+ void
+ Clear()
+ {
+ m_actions.clear();
+ m_signal_handled.clear();
+ }
+
+ protected:
+ std::vector<ResumeAction> m_actions;
+ mutable std::vector<bool> m_signal_handled;
+ };
+
+ struct ThreadStopInfo
+ {
+ lldb::StopReason reason;
+ union
+ {
+ // eStopTypeSignal
+ struct
+ {
+ uint32_t signo;
+ } signal;
+
+ // eStopTypeException
+ struct
+ {
+ uint64_t type;
+ uint32_t data_count;
+ lldb::addr_t data[2];
+ } exception;
+ } details;
+ };
+
+ //------------------------------------------------------------------
+ // NativeThreadProtocol
+ //------------------------------------------------------------------
+ class NativeThreadProtocol {
+
+ public:
+ NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) :
+ m_process (process),
+ m_tid (tid)
+ {
+ }
+
+ virtual ~NativeThreadProtocol()
+ {
+ }
+ virtual const char *GetName() = 0;
+ virtual lldb::StateType GetState () = 0;
+ virtual Error ReadRegister (uint32_t reg, RegisterValue &reg_value) = 0;
+ virtual Error WriteRegister (uint32_t reg, const RegisterValue &reg_value) = 0;
+ virtual Error SaveAllRegisters (lldb::DataBufferSP &data_sp) = 0;
+ virtual Error RestoreAllRegisters (lldb::DataBufferSP &data_sp) = 0;
+ virtual bool GetStopReason (ThreadStopInfo &stop_info) = 0;
+
+ lldb::tid_t
+ GetID() const
+ {
+ return m_tid;
+ }
+ protected:
+ NativeProcessProtocol *m_process;
+ lldb::tid_t m_tid;
+ };
+
+
+ //------------------------------------------------------------------
+ // NativeProcessProtocol
+ //------------------------------------------------------------------
+ class NativeProcessProtocol {
+ public:
+
+ static NativeProcessProtocol *
+ CreateInstance (lldb::pid_t pid);
+
+ // lldb_private::Host calls should be used to launch a process for debugging, and
+ // then the process should be attached to. When attaching to a process
+ // lldb_private::Host calls should be used to locate the process to attach to,
+ // and then this function should be called.
+ NativeProcessProtocol (lldb::pid_t pid) :
+ m_pid (pid),
+ m_threads(),
+ m_threads_mutex (Mutex::eMutexTypeRecursive),
+ m_state (lldb::eStateInvalid),
+ m_exit_status(0),
+ m_exit_description()
+ {
+ }
+
+ public:
+ virtual ~NativeProcessProtocol ()
+ {
+ }
+
+ virtual Error Resume (const ResumeActionList &resume_actions) = 0;
+ virtual Error Halt () = 0;
+ virtual Error Detach () = 0;
+ virtual Error Signal (int signo) = 0;
+ virtual Error Kill () = 0;
+
+ virtual Error ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0;
+ virtual Error WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0;
+ virtual Error AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0;
+ virtual Error DeallocateMemory (lldb::addr_t addr) = 0;
+
+ virtual lldb::addr_t GetSharedLibraryInfoAddress () = 0;
+
+ virtual bool IsAlive () = 0;
+ virtual size_t UpdateThreads () = 0;
+ virtual bool GetArchitecture (ArchSpec &arch) = 0;
+
+ //----------------------------------------------------------------------
+ // Breakpoint functions
+ //----------------------------------------------------------------------
+ virtual Error SetBreakpoint (lldb::addr_t addr, size_t size, bool hardware) = 0;
+ virtual Error RemoveBreakpoint (lldb::addr_t addr, size_t size) = 0;
+
+ //----------------------------------------------------------------------
+ // Watchpoint functions
+ //----------------------------------------------------------------------
+ virtual uint32_t GetMaxWatchpoints () = 0;
+ virtual Error SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0;
+ virtual Error RemoveWatchpoint (lldb::addr_t addr) = 0;
+
+
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ lldb::pid_t
+ GetID() const
+ {
+ return m_pid;
+ }
+
+ lldb::StateType
+ GetState () const
+ {
+ return m_state;
+ }
+
+ bool
+ IsRunning () const
+ {
+ return m_state == lldb::eStateRunning || IsStepping();
+ }
+
+ bool
+ IsStepping () const
+ {
+ return m_state == lldb::eStateStepping;
+ }
+
+ bool
+ CanResume () const
+ {
+ return m_state == lldb::eStateStopped;
+ }
+
+
+ void
+ SetState (lldb::StateType state)
+ {
+ m_state = state;
+ }
+
+ //----------------------------------------------------------------------
+ // Exit Status
+ //----------------------------------------------------------------------
+ virtual bool
+ GetExitStatus (int *status)
+ {
+ if (m_state == lldb::eStateExited)
+ {
+ *status = m_exit_status;
+ return true;
+ }
+ *status = 0;
+ return false;
+ }
+ virtual bool
+ SetExitStatus (int status, const char *exit_description)
+ {
+ // Exit status already set
+ if (m_state == lldb::eStateExited)
+ return false;
+ m_state = lldb::eStateExited;
+ m_exit_status = status;
+ if (exit_description && exit_description[0])
+ m_exit_description = exit_description;
+ else
+ m_exit_description.clear();
+ return true;
+ }
+
+ //----------------------------------------------------------------------
+ // Access to threads
+ //----------------------------------------------------------------------
+ lldb::NativeThreadProtocolSP
+ GetThreadAtIndex (uint32_t idx)
+ {
+ Mutex::Locker locker(m_threads_mutex);
+ if (idx < m_threads.size())
+ return m_threads[idx];
+ return lldb::NativeThreadProtocolSP();
+ }
+
+ lldb::NativeThreadProtocolSP
+ GetThreadByID (lldb::tid_t tid)
+ {
+ Mutex::Locker locker(m_threads_mutex);
+ for (auto thread_sp : m_threads)
+ {
+ if (thread_sp->GetID() == tid)
+ return thread_sp;
+ }
+ return lldb::NativeThreadProtocolSP();
+ }
+
+ protected:
+ lldb::pid_t m_pid;
+ std::vector<lldb::NativeThreadProtocolSP> m_threads;
+ mutable Mutex m_threads_mutex;
+ lldb::StateType m_state;
+ int m_exit_status;
+ std::string m_exit_description;
+ };
+
+}
+#endif // #ifndef liblldb_Debug_h_
diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h
index 7ca582402b32..607efa029c09 100644
--- a/include/lldb/Host/File.h
+++ b/include/lldb/Host/File.h
@@ -40,46 +40,13 @@ public:
eOpenOptionTruncate = (1u << 3), // Truncate file when opening
eOpenOptionNonBlocking = (1u << 4), // File reads
eOpenOptionCanCreate = (1u << 5), // Create file if doesn't already exist
- eOpenOptionCanCreateNewOnly = (1u << 6) // Can create file only if it doesn't already exist
+ eOpenOptionCanCreateNewOnly = (1u << 6), // Can create file only if it doesn't already exist
+ eOpenoptionDontFollowSymlinks = (1u << 7)
};
static mode_t
ConvertOpenOptionsForPOSIXOpen (uint32_t open_options);
- enum Permissions
- {
- ePermissionsUserRead = (1u << 8),
- ePermissionsUserWrite = (1u << 7),
- ePermissionsUserExecute = (1u << 6),
- ePermissionsGroupRead = (1u << 5),
- ePermissionsGroupWrite = (1u << 4),
- ePermissionsGroupExecute = (1u << 3),
- ePermissionsWorldRead = (1u << 2),
- ePermissionsWorldWrite = (1u << 1),
- ePermissionsWorldExecute = (1u << 0),
-
- ePermissionsUserRW = (ePermissionsUserRead | ePermissionsUserWrite | 0 ),
- ePermissionsUserRX = (ePermissionsUserRead | 0 | ePermissionsUserExecute ),
- ePermissionsUserRWX = (ePermissionsUserRead | ePermissionsUserWrite | ePermissionsUserExecute ),
-
- ePermissionsGroupRW = (ePermissionsGroupRead | ePermissionsGroupWrite | 0 ),
- ePermissionsGroupRX = (ePermissionsGroupRead | 0 | ePermissionsGroupExecute ),
- ePermissionsGroupRWX = (ePermissionsGroupRead | ePermissionsGroupWrite | ePermissionsGroupExecute ),
-
- ePermissionsWorldRW = (ePermissionsWorldRead | ePermissionsWorldWrite | 0 ),
- ePermissionsWorldRX = (ePermissionsWorldRead | 0 | ePermissionsWorldExecute ),
- ePermissionsWorldRWX = (ePermissionsWorldRead | ePermissionsWorldWrite | ePermissionsWorldExecute ),
-
- ePermissionsEveryoneR = (ePermissionsUserRead | ePermissionsGroupRead | ePermissionsWorldRead ),
- ePermissionsEveryoneW = (ePermissionsUserWrite | ePermissionsGroupWrite | ePermissionsWorldWrite ),
- ePermissionsEveryoneX = (ePermissionsUserExecute | ePermissionsGroupExecute | ePermissionsWorldExecute ),
-
- ePermissionsEveryoneRW = (ePermissionsEveryoneR | ePermissionsEveryoneW | 0 ),
- ePermissionsEveryoneRX = (ePermissionsEveryoneR | 0 | ePermissionsEveryoneX ),
- ePermissionsEveryoneRWX = (ePermissionsEveryoneR | ePermissionsEveryoneW | ePermissionsEveryoneX ),
- ePermissionsDefault = (ePermissionsUserRW | ePermissionsGroupRead)
- };
-
File() :
m_descriptor (kInvalidDescriptor),
m_stream (kInvalidStream),
@@ -120,7 +87,7 @@ public:
//------------------------------------------------------------------
File (const char *path,
uint32_t options,
- uint32_t permissions = ePermissionsDefault);
+ uint32_t permissions = lldb::eFilePermissionsFileDefault);
//------------------------------------------------------------------
/// Constructor with FileSpec.
@@ -142,7 +109,7 @@ public:
//------------------------------------------------------------------
File (const FileSpec& filespec,
uint32_t options,
- uint32_t permissions = ePermissionsDefault);
+ uint32_t permissions = lldb::eFilePermissionsFileDefault);
File (int fd, bool tranfer_ownership) :
m_descriptor (fd),
@@ -236,7 +203,7 @@ public:
Error
Open (const char *path,
uint32_t options,
- uint32_t permissions = ePermissionsDefault);
+ uint32_t permissions = lldb::eFilePermissionsFileDefault);
Error
Close ();
diff --git a/include/lldb/Host/FileSpec.h b/include/lldb/Host/FileSpec.h
index dfc6b711ae4a..086c8f200567 100644
--- a/include/lldb/Host/FileSpec.h
+++ b/include/lldb/Host/FileSpec.h
@@ -420,6 +420,21 @@ public:
FileType
GetFileType () const;
+ //------------------------------------------------------------------
+ /// Return the current permissions of the path.
+ ///
+ /// Returns a bitmask for the current permissions of the file
+ /// ( zero or more of the permission bits defined in
+ /// File::Permissions).
+ ///
+ /// @return
+ /// Zero if the file doesn't exist or we are unable to get
+ /// information for the file, otherwise one or more permission
+ /// bits from the File::Permissions enumeration.
+ //------------------------------------------------------------------
+ uint32_t
+ GetPermissions () const;
+
bool
IsDirectory () const
{
@@ -636,7 +651,7 @@ public:
void
RemoveLastPathComponent ();
- const char*
+ ConstString
GetLastPathComponent () const;
//------------------------------------------------------------------
diff --git a/include/lldb/Host/Host.h b/include/lldb/Host/Host.h
index 1d667dee5a20..fe0f6f62b3bc 100644
--- a/include/lldb/Host/Host.h
+++ b/include/lldb/Host/Host.h
@@ -510,13 +510,28 @@ public:
const char *symbol_name,
Error &error);
- static uint32_t
- MakeDirectory (const char* path, mode_t mode);
+ static Error
+ MakeDirectory (const char* path, uint32_t mode);
+
+ static Error
+ GetFilePermissions (const char* path, uint32_t &file_permissions);
+
+ static Error
+ SetFilePermissions (const char* path, uint32_t file_permissions);
+ static Error
+ Symlink (const char *src, const char *dst);
+
+ static Error
+ Readlink (const char *path, char *buf, size_t buf_len);
+
+ static Error
+ Unlink (const char *path);
+
static lldb::user_id_t
OpenFile (const FileSpec& file_spec,
uint32_t flags,
- mode_t mode,
+ uint32_t mode,
Error &error);
static bool
diff --git a/include/lldb/Host/OptionParser.h b/include/lldb/Host/OptionParser.h
index 410e4d9f9468..ca83eeb1ed77 100644
--- a/include/lldb/Host/OptionParser.h
+++ b/include/lldb/Host/OptionParser.h
@@ -10,6 +10,10 @@
#ifndef liblldb_OptionParser_h_
#define liblldb_OptionParser_h_
+#include <string>
+
+struct option;
+
namespace lldb_private {
typedef struct Option
@@ -46,6 +50,7 @@ public:
static char* GetOptionArgument();
static int GetOptionIndex();
static int GetOptionErrorCause();
+ static std::string GetShortOptionString(struct option *long_options);
};
}
diff --git a/include/lldb/Interpreter/PythonDataObjects.h b/include/lldb/Interpreter/PythonDataObjects.h
index a54318159d14..2762d452c0c8 100644
--- a/include/lldb/Interpreter/PythonDataObjects.h
+++ b/include/lldb/Interpreter/PythonDataObjects.h
@@ -19,11 +19,7 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Flags.h"
#include "lldb/Interpreter/OptionValue.h"
-#if defined (__APPLE__)
-#include <Python/Python.h>
-#else
-#include <Python.h>
-#endif
+#include "lldb/lldb-python.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/ScriptInterpreterPython.h b/include/lldb/Interpreter/ScriptInterpreterPython.h
index 4b3dc61f3ee8..b729cb628007 100644
--- a/include/lldb/Interpreter/ScriptInterpreterPython.h
+++ b/include/lldb/Interpreter/ScriptInterpreterPython.h
@@ -17,12 +17,7 @@
#else
-#if defined (__APPLE__)
-#include <Python/Python.h>
-#else
-#include <Python.h>
-#endif
-
+#include "lldb/lldb-python.h"
#include "lldb/lldb-private.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Core/InputReader.h"
diff --git a/include/lldb/Symbol/TypeList.h b/include/lldb/Symbol/TypeList.h
index be7d35482da0..4f3f2c9bdbeb 100644
--- a/include/lldb/Symbol/TypeList.h
+++ b/include/lldb/Symbol/TypeList.h
@@ -12,6 +12,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Symbol/Type.h"
+#include "lldb/Utility/Iterable.h"
#include <map>
#include <functional>
@@ -51,6 +52,15 @@ public:
lldb::TypeSP
GetTypeAtIndex(uint32_t idx);
+
+ typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
+ typedef AdaptedIterable<collection, lldb::TypeSP, map_adapter> TypeIterable;
+
+ TypeIterable
+ Types ()
+ {
+ return TypeIterable(m_types);
+ }
void
ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const;
@@ -75,7 +85,6 @@ public:
RemoveMismatchedTypes (lldb::TypeClass type_class);
private:
- typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h
index 16f8ee7fc7d7..cc6c46cf0ec9 100644
--- a/include/lldb/Target/ABI.h
+++ b/include/lldb/Target/ABI.h
@@ -18,6 +18,8 @@
#include "lldb/Core/PluginInterface.h"
#include "lldb/lldb-private.h"
+#include "llvm/ADT/ArrayRef.h"
+
namespace lldb_private {
class ABI :
@@ -35,12 +37,7 @@ public:
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
- lldb::addr_t *arg1_ptr = NULL,
- lldb::addr_t *arg2_ptr = NULL,
- lldb::addr_t *arg3_ptr = NULL,
- lldb::addr_t *arg4_ptr = NULL,
- lldb::addr_t *arg5_ptr = NULL,
- lldb::addr_t *arg6_ptr = NULL) const = 0;
+ llvm::ArrayRef<lldb::addr_t> args) const = 0;
virtual bool
GetArgumentValues (Thread &thread,
diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h
index 93c0437da75d..0aaa67c2382c 100644
--- a/include/lldb/Target/LanguageRuntime.h
+++ b/include/lldb/Target/LanguageRuntime.h
@@ -67,6 +67,12 @@ public:
}
virtual bool
+ ExceptionBreakpointsAreSet ()
+ {
+ return false;
+ }
+
+ virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{
return false;
diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h
index 93cd67d66659..355c0528bed8 100644
--- a/include/lldb/Target/Platform.h
+++ b/include/lldb/Target/Platform.h
@@ -40,7 +40,8 @@ namespace lldb_private {
/// @li listing and getting info for existing processes
/// @li attaching and possibly debugging the platform's kernel
//----------------------------------------------------------------------
- class Platform : public PluginInterface
+ class Platform :
+ public PluginInterface
{
public:
@@ -214,8 +215,7 @@ namespace lldb_private {
bool
GetOSKernelDescription (std::string &s);
- // Returns the the hostname if we are connected, else the short plugin
- // name.
+ // Returns the the name of the platform
ConstString
GetName ();
@@ -269,6 +269,15 @@ namespace lldb_private {
{
return ArchSpec(); // Return an invalid architecture
}
+
+ virtual ConstString
+ GetRemoteWorkingDirectory()
+ {
+ return m_working_dir;
+ }
+
+ virtual bool
+ SetRemoteWorkingDirectory(const ConstString &path);
virtual const char *
GetUserName (uint32_t uid);
@@ -384,10 +393,13 @@ namespace lldb_private {
}
//------------------------------------------------------------------
- /// Subclasses should NOT need to implement this function as it uses
- /// the Platform::LaunchProcess() followed by Platform::Attach ()
+ /// Subclasses do not need to implement this function as it uses
+ /// the Platform::LaunchProcess() followed by Platform::Attach ().
+ /// Remote platforms will want to subclass this function in order
+ /// to be able to intercept STDIO and possibly launch a separate
+ /// process that will debug the debuggee.
//------------------------------------------------------------------
- lldb::ProcessSP
+ virtual lldb::ProcessSP
DebugProcess (ProcessLaunchInfo &launch_info,
Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new target, else use existing one
@@ -542,6 +554,12 @@ namespace lldb_private {
{
m_sdk_build = sdk_build;
}
+
+ ConstString
+ GetWorkingDirectory ();
+
+ bool
+ SetWorkingDirectory (const ConstString &path);
// There may be modules that we don't want to find by default for operations like "setting breakpoint by name".
// The platform will return "true" from this call if the passed in module happens to be one of these.
@@ -552,23 +570,19 @@ namespace lldb_private {
return false;
}
- virtual uint32_t
- MakeDirectory (const std::string &path,
- mode_t mode)
- {
- return UINT32_MAX;
- }
-
- // this need not be virtual: the core behavior is in
- // MakeDirectory(std::string,mode_t)
- uint32_t
- MakeDirectory (const FileSpec &spec,
- mode_t mode);
+ virtual Error
+ MakeDirectory (const char *path, uint32_t permissions);
+ virtual Error
+ GetFilePermissions (const char *path, uint32_t &file_permissions);
+
+ virtual Error
+ SetFilePermissions (const char *path, uint32_t file_permissions);
+
virtual lldb::user_id_t
OpenFile (const FileSpec& file_spec,
uint32_t flags,
- mode_t mode,
+ uint32_t mode,
Error &error)
{
return UINT64_MAX;
@@ -610,28 +624,54 @@ namespace lldb_private {
}
virtual Error
+ GetFile (const FileSpec& source,
+ const FileSpec& destination);
+
+ virtual Error
PutFile (const FileSpec& source,
const FileSpec& destination,
uint32_t uid = UINT32_MAX,
uint32_t gid = UINT32_MAX);
-
+
+ virtual Error
+ CreateSymlink (const char *src, // The name of the link is in src
+ const char *dst);// The symlink points to dst
+
+ //----------------------------------------------------------------------
+ /// Install a file or directory to the remote system.
+ ///
+ /// Install is similar to Platform::PutFile(), but it differs in that if
+ /// an application/framework/shared library is installed on a remote
+ /// platform and the remote platform requires something to be done to
+ /// register the application/framework/shared library, then this extra
+ /// registration can be done.
+ ///
+ /// @param[in] src
+ /// The source file/directory to install on the remote system.
+ ///
+ /// @param[in] dst
+ /// The destination file/directory where \a src will be installed.
+ /// If \a dst has no filename specified, then its filename will
+ /// be set from \a src. It \a dst has no directory specified, it
+ /// will use the platform working directory. If \a dst has a
+ /// directory specified, but the directory path is relative, the
+ /// platform working directory will be prepended to the relative
+ /// directory.
+ ///
+ /// @return
+ /// An error object that describes anything that went wrong.
+ //----------------------------------------------------------------------
+ virtual Error
+ Install (const FileSpec& src, const FileSpec& dst);
+
virtual size_t
GetEnvironment (StringList &environment);
- virtual Error
- GetFile (const FileSpec& source,
- const FileSpec& destination);
-
virtual bool
GetFileExists (const lldb_private::FileSpec& file_spec);
- virtual uint32_t
- GetFilePermissions (const lldb_private::FileSpec &file_spec,
- Error &error)
- {
- error.SetErrorStringWithFormat ("Platform::GetFilePermissions() is not supported in the %s platform", GetName().GetCString());
- return 0;
- }
+ virtual Error
+ Unlink (const char *path);
virtual bool
GetSupportsRSync ()
@@ -806,6 +846,7 @@ namespace lldb_private {
bool m_system_arch_set_while_connected;
ConstString m_sdk_sysroot; // the root location of where the SDK files are all located
ConstString m_sdk_build;
+ ConstString m_working_dir; // The working directory which is used when installing modules that have no install path set
std::string m_remote_url;
std::string m_name;
uint32_t m_major_os_version;
diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h
index aa7b5edc5af1..cda9b4f57118 100644
--- a/include/lldb/Target/Process.h
+++ b/include/lldb/Target/Process.h
@@ -1745,7 +1745,7 @@ public:
/// the error object is success.
//------------------------------------------------------------------
virtual Error
- Launch (const ProcessLaunchInfo &launch_info);
+ Launch (ProcessLaunchInfo &launch_info);
virtual Error
LoadCore ();
@@ -2502,11 +2502,7 @@ public:
ExecutionResults
RunThreadPlan (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
- bool stop_others,
- bool run_others,
- bool unwind_on_error,
- bool ignore_breakpoints,
- uint32_t timeout_usec,
+ const EvaluateExpressionOptions &options,
Stream &errors);
static const char *
@@ -3304,6 +3300,23 @@ public:
{
return m_thread_list;
}
+
+ // When ExtendedBacktraces are requested, the HistoryThreads that are
+ // created need an owner -- they're saved here in the Process. The
+ // threads in this list are not iterated over - driver programs need to
+ // request the extended backtrace calls starting from a root concrete
+ // thread one by one.
+ ThreadList &
+ GetExtendedThreadList ()
+ {
+ return m_extended_thread_list;
+ }
+
+ ThreadList::ThreadIterable
+ Threads ()
+ {
+ return m_thread_list.Threads();
+ }
uint32_t
GetNextThreadIndexID (uint64_t thread_id);
@@ -3670,6 +3683,8 @@ protected:
ThreadList m_thread_list_real; ///< The threads for this process as are known to the protocol we are debugging with
ThreadList m_thread_list; ///< The threads for this process as the user will see them. This is usually the same as
///< m_thread_list_real, but might be different if there is an OS plug-in creating memory threads
+ ThreadList m_extended_thread_list; ///< Owner for extended threads that may be generated, cleared on natural stops
+ uint32_t m_extended_thread_stop_id; ///< The natural stop id when extended_thread_list was last updated
std::vector<Notifications> m_notifications; ///< The list of notifications that this process can deliver.
std::vector<lldb::addr_t> m_image_tokens;
Listener &m_listener;
diff --git a/include/lldb/Target/RegisterCheckpoint.h b/include/lldb/Target/RegisterCheckpoint.h
new file mode 100644
index 000000000000..3e61e1490d4b
--- /dev/null
+++ b/include/lldb/Target/RegisterCheckpoint.h
@@ -0,0 +1,71 @@
+//===-- RegisterCheckpoint.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterCheckpoint_h_
+#define liblldb_RegisterCheckpoint_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/UserID.h"
+#include "lldb/Target/StackID.h"
+
+namespace lldb_private {
+
+ // Inherit from UserID in case pushing/popping all register values can be
+ // done using a 64 bit integer that holds a baton/cookie instead of actually
+ // having to read all register values into a buffer
+ class RegisterCheckpoint : public UserID
+ {
+ public:
+
+ enum class Reason {
+ // An expression is about to be run on the thread if the protocol that
+ // talks to the debuggee supports checkpointing the registers using a
+ // push/pop then the UserID base class in the RegisterCheckpoint can
+ // be used to store the baton/cookie that refers to the remote saved
+ // state.
+ eExpression,
+ // The register checkpoint wants the raw register bytes, so they must
+ // be read into m_data_sp, or the save/restore checkpoint should fail.
+ eDataBackup
+ };
+
+ RegisterCheckpoint(Reason reason) :
+ UserID(0),
+ m_data_sp (),
+ m_reason(reason)
+ {
+ }
+
+ ~RegisterCheckpoint()
+ {
+ }
+
+ lldb::DataBufferSP &
+ GetData()
+ {
+ return m_data_sp;
+ }
+
+ const lldb::DataBufferSP &
+ GetData() const
+ {
+ return m_data_sp;
+ }
+
+ protected:
+ lldb::DataBufferSP m_data_sp;
+ Reason m_reason;
+
+ // Make RegisterCheckpointSP if you wish to share the data in this class.
+ DISALLOW_COPY_AND_ASSIGN(RegisterCheckpoint);
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_RegisterCheckpoint_h_
diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h
index 7da462700110..421acc03cb22 100644
--- a/include/lldb/Target/RegisterContext.h
+++ b/include/lldb/Target/RegisterContext.h
@@ -59,6 +59,18 @@ public:
virtual bool
WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value) = 0;
+ virtual bool
+ ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+ {
+ return false;
+ }
+
+ virtual bool
+ WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+ {
+ return false;
+ }
+
// These two functions are used to implement "push" and "pop" of register states. They are used primarily
// for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then
// restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues.
@@ -67,10 +79,10 @@ public:
// so these API's should only be used when this behavior is needed.
virtual bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp) = 0;
-
+ ReadAllRegisterValues (lldb_private::RegisterCheckpoint &reg_checkpoint);
+
virtual bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0;
+ WriteAllRegisterValues (const lldb_private::RegisterCheckpoint &reg_checkpoint);
bool
CopyFromRegisterContext (lldb::RegisterContextSP context);
diff --git a/include/lldb/Target/SystemRuntime.h b/include/lldb/Target/SystemRuntime.h
index 6c0a4205d5f2..7a0703e6cc34 100644
--- a/include/lldb/Target/SystemRuntime.h
+++ b/include/lldb/Target/SystemRuntime.h
@@ -127,7 +127,7 @@ public:
/// An empty vector may be returned if no thread origin extended
/// backtrace capabilities are available.
//------------------------------------------------------------------
- virtual std::vector<ConstString>
+ virtual const std::vector<ConstString> &
GetExtendedBacktraceTypes ();
//------------------------------------------------------------------
@@ -158,13 +158,16 @@ public:
/// An empty ThreadSP will be returned if no thread origin is available.
//------------------------------------------------------------------
virtual lldb::ThreadSP
- GetExtendedBacktrace (lldb::ThreadSP thread, ConstString type);
+ GetExtendedBacktraceThread (lldb::ThreadSP thread, ConstString type);
protected:
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
Process *m_process;
+
+ std::vector<ConstString> m_types;
+
private:
DISALLOW_COPY_AND_ASSIGN (SystemRuntime);
};
diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h
index 1c90ea6f15eb..d874891a6aff 100644
--- a/include/lldb/Target/Target.h
+++ b/include/lldb/Target/Target.h
@@ -189,8 +189,10 @@ public:
m_unwind_on_error(true),
m_ignore_breakpoints (false),
m_keep_in_memory(false),
- m_run_others(true),
+ m_try_others(true),
+ m_stop_others(true),
m_debug(false),
+ m_trap_exceptions(true),
m_use_dynamic(lldb::eNoDynamicValues),
m_timeout_usec(default_timeout)
{}
@@ -201,11 +203,10 @@ public:
return m_execution_policy;
}
- EvaluateExpressionOptions&
+ void
SetExecutionPolicy (ExecutionPolicy policy = eExecutionPolicyAlways)
{
m_execution_policy = policy;
- return *this;
}
lldb::LanguageType
@@ -214,11 +215,10 @@ public:
return m_language;
}
- EvaluateExpressionOptions&
+ void
SetLanguage(lldb::LanguageType language)
{
m_language = language;
- return *this;
}
bool
@@ -227,11 +227,10 @@ public:
return m_coerce_to_id;
}
- EvaluateExpressionOptions&
+ void
SetCoerceToId (bool coerce = true)
{
m_coerce_to_id = coerce;
- return *this;
}
bool
@@ -240,11 +239,10 @@ public:
return m_unwind_on_error;
}
- EvaluateExpressionOptions&
+ void
SetUnwindOnError (bool unwind = false)
{
m_unwind_on_error = unwind;
- return *this;
}
bool
@@ -253,11 +251,10 @@ public:
return m_ignore_breakpoints;
}
- EvaluateExpressionOptions&
+ void
SetIgnoreBreakpoints (bool ignore = false)
{
m_ignore_breakpoints = ignore;
- return *this;
}
bool
@@ -266,11 +263,10 @@ public:
return m_keep_in_memory;
}
- EvaluateExpressionOptions&
+ void
SetKeepInMemory (bool keep = true)
{
m_keep_in_memory = keep;
- return *this;
}
lldb::DynamicValueType
@@ -279,11 +275,10 @@ public:
return m_use_dynamic;
}
- EvaluateExpressionOptions&
+ void
SetUseDynamic (lldb::DynamicValueType dynamic = lldb::eDynamicCanRunTarget)
{
m_use_dynamic = dynamic;
- return *this;
}
uint32_t
@@ -292,24 +287,34 @@ public:
return m_timeout_usec;
}
- EvaluateExpressionOptions&
+ void
SetTimeoutUsec (uint32_t timeout = 0)
{
m_timeout_usec = timeout;
- return *this;
}
bool
- GetRunOthers () const
+ GetTryAllThreads () const
{
- return m_run_others;
+ return m_try_others;
}
- EvaluateExpressionOptions&
- SetRunOthers (bool run_others = true)
+ void
+ SetTryAllThreads (bool try_others = true)
+ {
+ m_try_others = try_others;
+ }
+
+ bool
+ GetStopOthers () const
+ {
+ return m_stop_others;
+ }
+
+ void
+ SetStopOthers (bool stop_others = true)
{
- m_run_others = run_others;
- return *this;
+ m_stop_others = stop_others;
}
bool
@@ -318,11 +323,22 @@ public:
return m_debug;
}
- EvaluateExpressionOptions&
+ void
SetDebug(bool b)
{
m_debug = b;
- return *this;
+ }
+
+ bool
+ GetTrapExceptions() const
+ {
+ return m_trap_exceptions;
+ }
+
+ void
+ SetTrapExceptions (bool b)
+ {
+ m_trap_exceptions = b;
}
private:
@@ -332,8 +348,10 @@ private:
bool m_unwind_on_error;
bool m_ignore_breakpoints;
bool m_keep_in_memory;
- bool m_run_others;
+ bool m_try_others;
+ bool m_stop_others;
bool m_debug;
+ bool m_trap_exceptions;
lldb::DynamicValueType m_use_dynamic;
uint32_t m_timeout_usec;
};
@@ -741,9 +759,23 @@ public:
SymbolsDidLoad (ModuleList &module_list);
void
- ClearModules();
+ ClearModules(bool delete_locations);
//------------------------------------------------------------------
+ /// Called as the last function in Process::DidExec().
+ ///
+ /// Process::DidExec() will clear a lot of state in the process,
+ /// then try to reload a dynamic loader plugin to discover what
+ /// binaries are currently available and then this function should
+ /// be called to allow the target to do any cleanup after everything
+ /// has been figured out. It can remove breakpoints that no longer
+ /// make sense as the exec might have changed the target
+ /// architecture, and unloaded some modules that might get deleted.
+ //------------------------------------------------------------------
+ void
+ DidExec ();
+
+ //------------------------------------------------------------------
/// Gets the module for the main executable.
///
/// Each process has a notion of a main executable that is the file
@@ -1009,6 +1041,12 @@ public:
ClangASTImporter *
GetClangASTImporter();
+ //----------------------------------------------------------------------
+ // Install any files through the platform that need be to installed
+ // prior to launching or attaching.
+ //----------------------------------------------------------------------
+ Error
+ Install(ProcessLaunchInfo *launch_info);
// Since expressions results can persist beyond the lifetime of a process,
// and the const expression results are available after a process is gone,
diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h
index 7dac37caa200..4f78b0fe6998 100644
--- a/include/lldb/Target/Thread.h
+++ b/include/lldb/Target/Thread.h
@@ -17,6 +17,7 @@
#include "lldb/Core/UserID.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/RegisterCheckpoint.h"
#include "lldb/Target/StackFrameList.h"
#define LLDB_THREAD_MAX_STOP_EXC_DATA 8
@@ -130,79 +131,12 @@ public:
DISALLOW_COPY_AND_ASSIGN (ThreadEventData);
};
- // TODO: You shouldn't just checkpoint the register state alone, so this should get
- // moved to protected. To do that ThreadStateCheckpoint needs to be returned as a token...
- class RegisterCheckpoint
- {
- public:
-
- RegisterCheckpoint() :
- m_stack_id (),
- m_data_sp ()
- {
- }
-
- RegisterCheckpoint (const StackID &stack_id) :
- m_stack_id (stack_id),
- m_data_sp ()
- {
- }
-
- ~RegisterCheckpoint()
- {
- }
-
- const RegisterCheckpoint&
- operator= (const RegisterCheckpoint &rhs)
- {
- if (this != &rhs)
- {
- this->m_stack_id = rhs.m_stack_id;
- this->m_data_sp = rhs.m_data_sp;
- }
- return *this;
- }
-
- RegisterCheckpoint (const RegisterCheckpoint &rhs) :
- m_stack_id (rhs.m_stack_id),
- m_data_sp (rhs.m_data_sp)
- {
- }
-
- const StackID &
- GetStackID()
- {
- return m_stack_id;
- }
-
- void
- SetStackID (const StackID &stack_id)
- {
- m_stack_id = stack_id;
- }
-
- lldb::DataBufferSP &
- GetData()
- {
- return m_data_sp;
- }
-
- const lldb::DataBufferSP &
- GetData() const
- {
- return m_data_sp;
- }
-
- protected:
- StackID m_stack_id;
- lldb::DataBufferSP m_data_sp;
- };
struct ThreadStateCheckpoint
{
uint32_t orig_stop_id; // Dunno if I need this yet but it is an interesting bit of data.
lldb::StopInfoSP stop_info_sp; // You have to restore the stop info or you might continue with the wrong signals.
- RegisterCheckpoint register_backup; // You need to restore the registers, of course...
+ lldb::RegisterCheckpointSP register_backup_sp; // You need to restore the registers, of course...
uint32_t current_inlined_depth;
lldb::addr_t current_inlined_pc;
};
@@ -339,18 +273,33 @@ public:
return NULL;
}
+ virtual void
+ SetName (const char *name)
+ {
+ }
+
virtual lldb::queue_id_t
GetQueueID ()
{
return LLDB_INVALID_QUEUE_ID;
}
+ virtual void
+ SetQueueID (lldb::queue_id_t new_val)
+ {
+ }
+
virtual const char *
GetQueueName ()
{
return NULL;
}
+ virtual void
+ SetQueueName (const char *name)
+ {
+ }
+
virtual uint32_t
GetStackFrameCount()
{
@@ -529,21 +478,6 @@ public:
QueueFundamentalPlan (bool abort_other_plans);
//------------------------------------------------------------------
- /// Queues the plan used to step over a breakpoint at the current PC of \a thread.
- /// The default version returned by Process handles trap based breakpoints, and
- /// will disable the breakpoint, single step over it, then re-enable it.
- ///
- /// @param[in] abort_other_plans
- /// \b true if we discard the currently queued plans and replace them with this one.
- /// Otherwise this plan will go on the end of the plan stack.
- ///
- /// @return
- /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued.
- //------------------------------------------------------------------
- virtual lldb::ThreadPlanSP
- QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans);
-
- //------------------------------------------------------------------
/// Queues the plan used to step one instruction from the current PC of \a thread.
///
/// @param[in] step_over
@@ -728,14 +662,6 @@ public:
bool stop_others,
uint32_t frame_idx);
- virtual lldb::ThreadPlanSP
- QueueThreadPlanForCallFunction (bool abort_other_plans,
- Address& function,
- lldb::addr_t arg,
- bool stop_other_threads,
- bool unwind_on_error = false,
- bool ignore_breakpoints = true);
-
//------------------------------------------------------------------
// Thread Plan accessors:
//------------------------------------------------------------------
@@ -879,7 +805,7 @@ public:
void
SetTracer (lldb::ThreadPlanTracerSP &tracer_sp);
-
+
//------------------------------------------------------------------
// Get the thread index ID. The index ID that is guaranteed to not
// be re-used by a process. They start at 1 and increase with each
@@ -888,8 +814,25 @@ public:
//------------------------------------------------------------------
uint32_t
GetIndexID () const;
-
-
+
+ //------------------------------------------------------------------
+ // Get the originating thread's index ID.
+ // In the case of an "extended" thread -- a thread which represents
+ // the stack that enqueued/spawned work that is currently executing --
+ // we need to provide the IndexID of the thread that actually did
+ // this work. We don't want to just masquerade as that thread's IndexID
+ // by using it in our own IndexID because that way leads to madness -
+ // but the driver program which is iterating over extended threads
+ // may ask for the OriginatingThreadID to display that information
+ // to the user.
+ // Normal threads will return the same thing as GetIndexID();
+ //------------------------------------------------------------------
+ virtual uint32_t
+ GetExtendedBacktraceOriginatingIndexID ()
+ {
+ return GetIndexID ();
+ }
+
//------------------------------------------------------------------
// The API ID is often the same as the Thread::GetID(), but not in
// all cases. Thread::GetID() is the user visible thread ID that
@@ -1001,6 +944,33 @@ public:
void
SetShouldReportStop (Vote vote);
+ //----------------------------------------------------------------------
+ /// Sets the extended backtrace token for this thread
+ ///
+ /// Some Thread subclasses may maintain a token to help with providing
+ /// an extended backtrace. The SystemRuntime plugin will set/request this.
+ ///
+ /// @param [in] token
+ //----------------------------------------------------------------------
+ virtual void
+ SetExtendedBacktraceToken (uint64_t token) { }
+
+ //----------------------------------------------------------------------
+ /// Gets the extended backtrace token for this thread
+ ///
+ /// Some Thread subclasses may maintain a token to help with providing
+ /// an extended backtrace. The SystemRuntime plugin will set/request this.
+ ///
+ /// @return
+ /// The token needed by the SystemRuntime to create an extended backtrace.
+ /// LLDB_INVALID_ADDRESS is returned if no token is available.
+ //----------------------------------------------------------------------
+ virtual uint64_t
+ GetExtendedBacktraceToken ()
+ {
+ return LLDB_INVALID_ADDRESS;
+ }
+
protected:
friend class ThreadPlan;
@@ -1027,16 +997,6 @@ protected:
typedef std::vector<lldb::ThreadPlanSP> plan_stack;
- virtual bool
- SaveFrameZeroState (RegisterCheckpoint &checkpoint);
-
- virtual bool
- RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint);
-
- // register_data_sp must be a DataSP passed to ReadAllRegisterValues.
- bool
- ResetFrameZeroRegisters (lldb::DataBufferSP register_data_sp);
-
virtual lldb_private::Unwind *
GetUnwinder ();
@@ -1058,12 +1018,6 @@ protected:
lldb::StackFrameListSP
GetStackFrameList ();
- struct ThreadState
- {
- uint32_t orig_stop_id;
- lldb::StopInfoSP stop_info_sp;
- RegisterCheckpoint register_backup;
- };
//------------------------------------------------------------------
// Classes that inherit from Process can see and modify these
diff --git a/include/lldb/Target/ThreadList.h b/include/lldb/Target/ThreadList.h
index ddf49b002ecf..f4dfdb23ec0f 100644
--- a/include/lldb/Target/ThreadList.h
+++ b/include/lldb/Target/ThreadList.h
@@ -14,6 +14,7 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/UserID.h"
+#include "lldb/Utility/Iterable.h"
// FIXME: Currently this is a thread list with lots of functionality for use only by
@@ -69,6 +70,15 @@ public:
// is a unique index assigned
lldb::ThreadSP
GetThreadAtIndex (uint32_t idx, bool can_update = true);
+
+ typedef std::vector<lldb::ThreadSP> collection;
+ typedef LockingAdaptedIterable<collection, lldb::ThreadSP, vector_adapter> ThreadIterable;
+
+ ThreadIterable
+ Threads ()
+ {
+ return ThreadIterable(m_threads, GetMutex());
+ }
lldb::ThreadSP
FindThreadByID (lldb::tid_t tid, bool can_update = true);
@@ -145,7 +155,6 @@ protected:
void
NotifySelectedThreadChanged (lldb::tid_t tid);
- typedef std::vector<lldb::ThreadSP> collection;
//------------------------------------------------------------------
// Classes that inherit from Process can see and modify these
//------------------------------------------------------------------
diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h
index 7b8efb60b880..18f1d0facbf6 100644
--- a/include/lldb/Target/ThreadPlanCallFunction.h
+++ b/include/lldb/Target/ThreadPlanCallFunction.h
@@ -18,6 +18,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
+#include "llvm/ADT/ArrayRef.h"
+
namespace lldb_private {
class ThreadPlanCallFunction : public ThreadPlan
@@ -29,25 +31,8 @@ public:
ThreadPlanCallFunction (Thread &thread,
const Address &function,
const ClangASTType &return_type,
- lldb::addr_t arg,
- bool stop_other_threads,
- bool unwind_on_error = true,
- bool ignore_breakpoints = false,
- lldb::addr_t *this_arg = 0,
- lldb::addr_t *cmd_arg = 0);
-
- ThreadPlanCallFunction (Thread &thread,
- const Address &function,
- const ClangASTType &return_type,
- bool stop_other_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- lldb::addr_t *arg1_ptr = NULL,
- lldb::addr_t *arg2_ptr = NULL,
- lldb::addr_t *arg3_ptr = NULL,
- lldb::addr_t *arg4_ptr = NULL,
- lldb::addr_t *arg5_ptr = NULL,
- lldb::addr_t *arg6_ptr = NULL);
+ llvm::ArrayRef<lldb::addr_t> args,
+ const EvaluateExpressionOptions &options);
virtual
~ThreadPlanCallFunction ();
@@ -171,10 +156,13 @@ private:
bool m_valid;
bool m_stop_other_threads;
+ bool m_unwind_on_error;
+ bool m_ignore_breakpoints;
+ bool m_debug_execution;
+ bool m_trap_exceptions;
Address m_function_addr;
Address m_start_addr;
lldb::addr_t m_function_sp;
- Thread::RegisterCheckpoint m_register_backup;
lldb::ThreadPlanSP m_subplan_sp;
LanguageRuntime *m_cxx_language_runtime;
LanguageRuntime *m_objc_language_runtime;
@@ -187,9 +175,9 @@ private:
ClangASTType m_return_type;
lldb::ValueObjectSP m_return_valobj_sp; // If this contains a valid pointer, use the ABI to extract values when complete
bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that.
+ bool m_should_clear_objc_exception_bp;
+ bool m_should_clear_cxx_exception_bp;
lldb::addr_t m_stop_address; // This is the address we stopped at. Also set in DoTakedown;
- bool m_unwind_on_error;
- bool m_ignore_breakpoints;
DISALLOW_COPY_AND_ASSIGN (ThreadPlanCallFunction);
};
diff --git a/include/lldb/Target/ThreadPlanCallUserExpression.h b/include/lldb/Target/ThreadPlanCallUserExpression.h
index 7a7ec33049e0..5eb7cc1cd452 100644
--- a/include/lldb/Target/ThreadPlanCallUserExpression.h
+++ b/include/lldb/Target/ThreadPlanCallUserExpression.h
@@ -20,6 +20,8 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "llvm/ADT/ArrayRef.h"
+
namespace lldb_private {
class ThreadPlanCallUserExpression : public ThreadPlanCallFunction
@@ -27,12 +29,8 @@ class ThreadPlanCallUserExpression : public ThreadPlanCallFunction
public:
ThreadPlanCallUserExpression (Thread &thread,
Address &function,
- lldb::addr_t arg,
- bool stop_other_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- lldb::addr_t *this_arg,
- lldb::addr_t *cmd_arg,
+ llvm::ArrayRef<lldb::addr_t> args,
+ const EvaluateExpressionOptions &options,
ClangUserExpression::ClangUserExpressionSP &user_expression_sp);
virtual
diff --git a/include/lldb/Utility/Iterable.h b/include/lldb/Utility/Iterable.h
new file mode 100644
index 000000000000..9b91cae37eef
--- /dev/null
+++ b/include/lldb/Utility/Iterable.h
@@ -0,0 +1,225 @@
+//===-- Iterable.h ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Iterable_h_
+#define liblldb_Iterable_h_
+
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private
+{
+
+template <typename I, typename E> E map_adapter(I &iter)
+{
+ return iter->second;
+}
+
+template <typename I, typename E> E vector_adapter(I &iter)
+{
+ return *iter;
+}
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)> class AdaptedConstIterator
+{
+public:
+ typedef typename C::const_iterator BackingIterator;
+private:
+ BackingIterator m_iter;
+public:
+ // Wrapping constructor
+ AdaptedConstIterator (BackingIterator backing_iterator) :
+ m_iter(backing_iterator)
+ {
+ }
+
+ // Default-constructible
+ AdaptedConstIterator () :
+ m_iter()
+ {
+ }
+
+ // Copy-constructible
+ AdaptedConstIterator (const AdaptedConstIterator &rhs) :
+ m_iter(rhs.m_iter)
+ {
+ }
+
+ // Copy-assignable
+ AdaptedConstIterator &operator= (const AdaptedConstIterator &rhs)
+ {
+ m_iter = rhs.m_iter;
+ return *this;
+ }
+
+ // Destructible
+ ~AdaptedConstIterator () { }
+
+ // Comparable
+ bool operator== (const AdaptedConstIterator &rhs)
+ {
+ return m_iter == rhs.m_iter;
+ }
+
+ bool operator!= (const AdaptedConstIterator &rhs)
+ {
+ return m_iter != rhs.m_iter;
+ }
+
+ // Rvalue dereferenceable
+ E operator* ()
+ {
+ return (*A)(m_iter);
+ }
+
+ E operator-> ()
+ {
+ return (*A)(m_iter);
+ }
+
+ // Offset dereferenceable
+ E operator[] (typename BackingIterator::difference_type offset)
+ {
+ return AdaptedConstIterator(m_iter + offset);
+ }
+
+ // Incrementable
+ AdaptedConstIterator &operator++ ()
+ {
+ m_iter++;
+ return *this;
+ }
+
+ // Decrementable
+ AdaptedConstIterator &operator-- ()
+ {
+ m_iter--;
+ return *this;
+ }
+
+ // Compound assignment
+ AdaptedConstIterator &operator+= (typename BackingIterator::difference_type offset)
+ {
+ m_iter += offset;
+ return *this;
+ }
+
+ AdaptedConstIterator &operator-= (typename BackingIterator::difference_type offset)
+ {
+ m_iter -= offset;
+ return *this;
+ }
+
+ // Arithmetic
+ AdaptedConstIterator operator+ (typename BackingIterator::difference_type offset)
+ {
+ return AdaptedConstIterator(m_iter + offset);
+ }
+
+ AdaptedConstIterator operator- (typename BackingIterator::difference_type offset)
+ {
+ return AdaptedConstIterator(m_iter - offset);
+ }
+
+ // Comparable
+ bool operator< (AdaptedConstIterator &rhs)
+ {
+ return m_iter < rhs.m_iter;
+ }
+
+ bool operator<= (AdaptedConstIterator &rhs)
+ {
+ return m_iter <= rhs.m_iter;
+ }
+
+ bool operator> (AdaptedConstIterator &rhs)
+ {
+ return m_iter > rhs.m_iter;
+ }
+
+ bool operator>= (AdaptedConstIterator &rhs)
+ {
+ return m_iter >= rhs.m_iter;
+ }
+
+ friend AdaptedConstIterator operator+(typename BackingIterator::difference_type, AdaptedConstIterator &);
+ friend typename BackingIterator::difference_type operator-(AdaptedConstIterator &, AdaptedConstIterator &);
+ friend void swap(AdaptedConstIterator &, AdaptedConstIterator &);
+};
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)>
+AdaptedConstIterator<C, E, A> operator+ (typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type offset, AdaptedConstIterator<C, E, A> &rhs)
+{
+ return rhs.operator+(offset);
+}
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)>
+typename AdaptedConstIterator<C, E, A>::BackingIterator::difference_type operator- (AdaptedConstIterator<C, E, A> &lhs, AdaptedConstIterator<C, E, A> &rhs)
+{
+ return(lhs.m_iter - rhs.m_iter);
+}
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)>
+void swap (AdaptedConstIterator<C, E, A> &lhs, AdaptedConstIterator<C, E, A> &rhs)
+{
+ std::swap(lhs.m_iter, rhs.m_iter);
+}
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)> class AdaptedIterable
+{
+private:
+ const C &m_container;
+public:
+ AdaptedIterable (const C &container) :
+ m_container(container)
+ {
+ }
+
+ AdaptedConstIterator<C, E, A> begin ()
+ {
+ return AdaptedConstIterator<C, E, A>(m_container.begin());
+ }
+
+ AdaptedConstIterator<C, E, A> end ()
+ {
+ return AdaptedConstIterator<C, E, A>(m_container.end());
+ }
+};
+
+template <typename C, typename E, E (*A)(typename C::const_iterator &)> class LockingAdaptedIterable : public AdaptedIterable<C, E, A>
+{
+private:
+ Mutex *m_mutex = nullptr;
+public:
+ LockingAdaptedIterable (C &container, Mutex &mutex) :
+ AdaptedIterable<C,E,A>(container),
+ m_mutex(&mutex)
+ {
+ m_mutex->Lock();
+ }
+
+ LockingAdaptedIterable (LockingAdaptedIterable &&rhs) :
+ AdaptedIterable<C,E,A>(rhs),
+ m_mutex(rhs.m_mutex)
+ {
+ rhs.m_mutex = NULL;
+ }
+
+ ~LockingAdaptedIterable ()
+ {
+ if (m_mutex)
+ m_mutex->Unlock();
+ }
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(LockingAdaptedIterable);
+};
+
+}
+
+#endif
diff --git a/include/lldb/Utility/PythonPointer.h b/include/lldb/Utility/PythonPointer.h
index f782f7f1313c..fe90670fd2e1 100644
--- a/include/lldb/Utility/PythonPointer.h
+++ b/include/lldb/Utility/PythonPointer.h
@@ -12,11 +12,7 @@
#include <algorithm>
-#if defined (__APPLE__)
-#include <Python/Python.h>
-#else
-#include <Python.h>
-#endif
+#include "lldb/lldb-python.h"
namespace lldb_private {
diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h
index ae8c92be900b..0b341575be46 100644
--- a/include/lldb/lldb-enumerations.h
+++ b/include/lldb/lldb-enumerations.h
@@ -684,6 +684,48 @@ namespace lldb {
eAddressClassRuntime
} AddressClass;
+ //----------------------------------------------------------------------
+ // File Permissions
+ //
+ // Designed to mimic the unix file permission bits so they can be
+ // used with functions that set 'mode_t' to certain values for
+ // permissions.
+ //----------------------------------------------------------------------
+ typedef enum FilePermissions
+ {
+ eFilePermissionsUserRead = (1u << 8),
+ eFilePermissionsUserWrite = (1u << 7),
+ eFilePermissionsUserExecute = (1u << 6),
+ eFilePermissionsGroupRead = (1u << 5),
+ eFilePermissionsGroupWrite = (1u << 4),
+ eFilePermissionsGroupExecute = (1u << 3),
+ eFilePermissionsWorldRead = (1u << 2),
+ eFilePermissionsWorldWrite = (1u << 1),
+ eFilePermissionsWorldExecute = (1u << 0),
+
+ eFilePermissionsUserRW = (eFilePermissionsUserRead | eFilePermissionsUserWrite | 0 ),
+ eFileFilePermissionsUserRX = (eFilePermissionsUserRead | 0 | eFilePermissionsUserExecute ),
+ eFilePermissionsUserRWX = (eFilePermissionsUserRead | eFilePermissionsUserWrite | eFilePermissionsUserExecute ),
+
+ eFilePermissionsGroupRW = (eFilePermissionsGroupRead | eFilePermissionsGroupWrite | 0 ),
+ eFilePermissionsGroupRX = (eFilePermissionsGroupRead | 0 | eFilePermissionsGroupExecute ),
+ eFilePermissionsGroupRWX = (eFilePermissionsGroupRead | eFilePermissionsGroupWrite | eFilePermissionsGroupExecute ),
+
+ eFilePermissionsWorldRW = (eFilePermissionsWorldRead | eFilePermissionsWorldWrite | 0 ),
+ eFilePermissionsWorldRX = (eFilePermissionsWorldRead | 0 | eFilePermissionsWorldExecute ),
+ eFilePermissionsWorldRWX = (eFilePermissionsWorldRead | eFilePermissionsWorldWrite | eFilePermissionsWorldExecute ),
+
+ eFilePermissionsEveryoneR = (eFilePermissionsUserRead | eFilePermissionsGroupRead | eFilePermissionsWorldRead ),
+ eFilePermissionsEveryoneW = (eFilePermissionsUserWrite | eFilePermissionsGroupWrite | eFilePermissionsWorldWrite ),
+ eFilePermissionsEveryoneX = (eFilePermissionsUserExecute | eFilePermissionsGroupExecute | eFilePermissionsWorldExecute ),
+
+ eFilePermissionsEveryoneRW = (eFilePermissionsEveryoneR | eFilePermissionsEveryoneW | 0 ),
+ eFilePermissionsEveryoneRX = (eFilePermissionsEveryoneR | 0 | eFilePermissionsEveryoneX ),
+ eFilePermissionsEveryoneRWX = (eFilePermissionsEveryoneR | eFilePermissionsEveryoneW | eFilePermissionsEveryoneX ),
+ eFilePermissionsFileDefault = eFilePermissionsUserRW,
+ eFilePermissionsDirectoryDefault = eFilePermissionsUserRWX,
+ } FilePermissions;
+
} // namespace lldb
diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h
index cd8a5c2e8130..68d85f081e25 100644
--- a/include/lldb/lldb-forward.h
+++ b/include/lldb/lldb-forward.h
@@ -97,6 +97,7 @@ class FileSpecList;
class Flags;
class TypeCategoryImpl;
class FormatManager;
+class FormattersMatchCandidate;
class FuncUnwinders;
class Function;
class FunctionInfo;
@@ -162,6 +163,7 @@ class PythonDictionary;
class PythonInteger;
class PythonObject;
class PythonString;
+class RegisterCheckpoint;
class RegisterContext;
class RegisterLocation;
class RegisterLocationList;
@@ -329,6 +331,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::ProcessLaunchInfo> ProcessLaunchInfoSP;
typedef std::weak_ptr<lldb_private::Process> ProcessWP;
typedef std::shared_ptr<lldb_private::Property> PropertySP;
+ typedef std::shared_ptr<lldb_private::RegisterCheckpoint> RegisterCheckpointSP;
typedef std::shared_ptr<lldb_private::RegisterContext> RegisterContextSP;
typedef std::shared_ptr<lldb_private::RegularExpression> RegularExpressionSP;
typedef std::shared_ptr<lldb_private::ScriptInterpreterObject> ScriptInterpreterObjectSP;
diff --git a/include/lldb/lldb-private-enumerations.h b/include/lldb/lldb-private-enumerations.h
index e523b912eac6..98919422be58 100644
--- a/include/lldb/lldb-private-enumerations.h
+++ b/include/lldb/lldb-private-enumerations.h
@@ -133,7 +133,8 @@ typedef enum ExecutionResults
eExecutionDiscarded,
eExecutionInterrupted,
eExecutionHitBreakpoint,
- eExecutionTimedOut
+ eExecutionTimedOut,
+ eExecutionStoppedForDebug
} ExecutionResults;
typedef enum ObjCRuntimeVersions {
diff --git a/include/lldb/lldb-python.h b/include/lldb/lldb-python.h
index 229e3967e4a5..ce5c8176a3c3 100644
--- a/include/lldb/lldb-python.h
+++ b/include/lldb/lldb-python.h
@@ -18,11 +18,7 @@
#else
-#if defined (__APPLE__)
-#include <Python/Python.h>
-#else
#include <Python.h>
-#endif
#endif // LLDB_DISABLE_PYTHON
diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp
index 88c991b72054..10c0b7dea208 100644
--- a/source/API/SBDebugger.cpp
+++ b/source/API/SBDebugger.cpp
@@ -38,6 +38,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/State.h"
#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/Host/DynamicLibrary.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
@@ -47,6 +48,41 @@
using namespace lldb;
using namespace lldb_private;
+
+static lldb::DynamicLibrarySP
+LoadPlugin (const lldb::DebuggerSP &debugger_sp, const FileSpec& spec, Error& error)
+{
+ lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec));
+ if (dynlib_sp && dynlib_sp->IsValid())
+ {
+ typedef bool (*LLDBCommandPluginInit) (lldb::SBDebugger& debugger);
+
+ lldb::SBDebugger debugger_sb(debugger_sp);
+ // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) function.
+ // TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays
+ LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
+ if (init_func)
+ {
+ if (init_func(debugger_sb))
+ return dynlib_sp;
+ else
+ error.SetErrorString("plug-in refused to load (lldb::PluginInitialize(lldb::SBDebugger) returned false)");
+ }
+ else
+ {
+ error.SetErrorString("plug-in is missing the required initialization: lldb::PluginInitialize(lldb::SBDebugger)");
+ }
+ }
+ else
+ {
+ if (spec.Exists())
+ error.SetErrorString("this file does not represent a loadable dylib");
+ else
+ error.SetErrorString("no such file");
+ }
+ return lldb::DynamicLibrarySP();
+}
+
void
SBDebugger::Initialize ()
{
@@ -57,7 +93,7 @@ SBDebugger::Initialize ()
SBCommandInterpreter::InitializeSWIG ();
- Debugger::Initialize();
+ Debugger::Initialize(LoadPlugin);
}
void
@@ -804,6 +840,42 @@ SBDebugger::SetSelectedTarget (SBTarget &sb_target)
}
}
+SBPlatform
+SBDebugger::GetSelectedPlatform()
+{
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ SBPlatform sb_platform;
+ DebuggerSP debugger_sp(m_opaque_sp);
+ if (debugger_sp)
+ {
+ sb_platform.SetSP(debugger_sp->GetPlatformList().GetSelectedPlatform());
+ }
+ if (log)
+ {
+ log->Printf ("SBDebugger(%p)::GetSelectedPlatform () => SBPlatform(%p): %s", m_opaque_sp.get(),
+ sb_platform.GetSP().get(), sb_platform.GetName());
+ }
+ return sb_platform;
+}
+
+void
+SBDebugger::SetSelectedPlatform(SBPlatform &sb_platform)
+{
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ DebuggerSP debugger_sp(m_opaque_sp);
+ if (debugger_sp)
+ {
+ debugger_sp->GetPlatformList().SetSelectedPlatform(sb_platform.GetSP());
+ }
+ if (log)
+ {
+ log->Printf ("SBDebugger(%p)::SetSelectedPlatform (SBPlatform(%p) %s)", m_opaque_sp.get(),
+ sb_platform.GetSP().get(), sb_platform.GetName());
+ }
+}
+
void
SBDebugger::DispatchInput (void* baton, const void *data, size_t data_len)
{
diff --git a/source/API/SBExpressionOptions.cpp b/source/API/SBExpressionOptions.cpp
index 127b0cf13cdc..ae1c8f99df30 100644
--- a/source/API/SBExpressionOptions.cpp
+++ b/source/API/SBExpressionOptions.cpp
@@ -104,13 +104,25 @@ SBExpressionOptions::SetTimeoutInMicroSeconds (uint32_t timeout)
bool
SBExpressionOptions::GetTryAllThreads () const
{
- return m_opaque_ap->GetRunOthers ();
+ return m_opaque_ap->GetTryAllThreads ();
}
void
SBExpressionOptions::SetTryAllThreads (bool run_others)
{
- m_opaque_ap->SetRunOthers (run_others);
+ m_opaque_ap->SetTryAllThreads (run_others);
+}
+
+bool
+SBExpressionOptions::GetTrapExceptions () const
+{
+ return m_opaque_ap->GetTrapExceptions ();
+}
+
+void
+SBExpressionOptions::SetTrapExceptions (bool trap_exceptions)
+{
+ m_opaque_ap->SetTrapExceptions (trap_exceptions);
}
EvaluateExpressionOptions *
diff --git a/source/API/SBFileSpec.cpp b/source/API/SBFileSpec.cpp
index fc207d071dbc..4fd2866c9b05 100644
--- a/source/API/SBFileSpec.cpp
+++ b/source/API/SBFileSpec.cpp
@@ -121,6 +121,24 @@ SBFileSpec::GetDirectory() const
return s;
}
+void
+SBFileSpec::SetFilename(const char *filename)
+{
+ if (filename && filename[0])
+ m_opaque_ap->GetFilename().SetCString(filename);
+ else
+ m_opaque_ap->GetFilename().Clear();
+}
+
+void
+SBFileSpec::SetDirectory(const char *directory)
+{
+ if (directory && directory[0])
+ m_opaque_ap->GetDirectory().SetCString(directory);
+ else
+ m_opaque_ap->GetDirectory().Clear();
+}
+
uint32_t
SBFileSpec::GetPath (char *dst_path, size_t dst_len) const
{
diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp
index 5f5fc9292cdb..0285cf304d4d 100644
--- a/source/API/SBModule.cpp
+++ b/source/API/SBModule.cpp
@@ -162,6 +162,27 @@ SBModule::SetPlatformFileSpec (const lldb::SBFileSpec &platform_file)
return result;
}
+lldb::SBFileSpec
+SBModule::GetRemoteInstallFileSpec ()
+{
+ SBFileSpec sb_file_spec;
+ ModuleSP module_sp (GetSP ());
+ if (module_sp)
+ sb_file_spec.SetFileSpec (module_sp->GetRemoteInstallFileSpec());
+ return sb_file_spec;
+}
+
+bool
+SBModule::SetRemoteInstallFileSpec (lldb::SBFileSpec &file)
+{
+ ModuleSP module_sp (GetSP ());
+ if (module_sp)
+ {
+ module_sp->SetRemoteInstallFileSpec(file.ref());
+ return true;
+ }
+ return false;
+}
const uint8_t *
diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp
new file mode 100644
index 000000000000..9914852cead7
--- /dev/null
+++ b/source/API/SBPlatform.cpp
@@ -0,0 +1,632 @@
+//===-- SBPlatform.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBPlatform.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBFileSpec.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Host/File.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Platform.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// PlatformConnectOptions
+//----------------------------------------------------------------------
+struct PlatformConnectOptions {
+ PlatformConnectOptions(const char *url = NULL) :
+ m_url(),
+ m_rsync_options(),
+ m_rsync_remote_path_prefix(),
+ m_rsync_enabled(false),
+ m_rsync_omit_hostname_from_remote_path(false),
+ m_local_cache_directory ()
+ {
+ if (url && url[0])
+ m_url = url;
+ }
+
+ ~PlatformConnectOptions()
+ {
+ }
+
+ std::string m_url;
+ std::string m_rsync_options;
+ std::string m_rsync_remote_path_prefix;
+ bool m_rsync_enabled;
+ bool m_rsync_omit_hostname_from_remote_path;
+ ConstString m_local_cache_directory;
+};
+
+//----------------------------------------------------------------------
+// PlatformShellCommand
+//----------------------------------------------------------------------
+struct PlatformShellCommand {
+ PlatformShellCommand(const char *shell_command = NULL) :
+ m_command(),
+ m_working_dir(),
+ m_status(0),
+ m_signo(0),
+ m_timeout_sec(UINT32_MAX)
+ {
+ if (shell_command && shell_command[0])
+ m_command = shell_command;
+ }
+
+ ~PlatformShellCommand()
+ {
+ }
+
+ std::string m_command;
+ std::string m_working_dir;
+ std::string m_output;
+ int m_status;
+ int m_signo;
+ uint32_t m_timeout_sec;
+};
+//----------------------------------------------------------------------
+// SBPlatformConnectOptions
+//----------------------------------------------------------------------
+SBPlatformConnectOptions::SBPlatformConnectOptions (const char *url) :
+ m_opaque_ptr(new PlatformConnectOptions(url))
+{
+
+}
+
+SBPlatformConnectOptions::SBPlatformConnectOptions(const SBPlatformConnectOptions &rhs) :
+ m_opaque_ptr(new PlatformConnectOptions())
+{
+ *m_opaque_ptr = *rhs.m_opaque_ptr;
+}
+
+SBPlatformConnectOptions::~SBPlatformConnectOptions ()
+{
+ delete m_opaque_ptr;
+}
+
+void
+SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs)
+{
+ *m_opaque_ptr = *rhs.m_opaque_ptr;
+}
+
+const char *
+SBPlatformConnectOptions::GetURL()
+{
+ if (m_opaque_ptr->m_url.empty())
+ return NULL;
+ return m_opaque_ptr->m_url.c_str();
+}
+
+void
+SBPlatformConnectOptions::SetURL(const char *url)
+{
+ if (url && url[0])
+ m_opaque_ptr->m_url = url;
+ else
+ m_opaque_ptr->m_url.clear();
+}
+
+bool
+SBPlatformConnectOptions::GetRsyncEnabled()
+{
+ return m_opaque_ptr->m_rsync_enabled;
+}
+
+void
+SBPlatformConnectOptions::EnableRsync (const char *options,
+ const char *remote_path_prefix,
+ bool omit_hostname_from_remote_path)
+{
+ m_opaque_ptr->m_rsync_enabled = true;
+ m_opaque_ptr->m_rsync_omit_hostname_from_remote_path = omit_hostname_from_remote_path;
+ if (remote_path_prefix && remote_path_prefix[0])
+ m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
+ else
+ m_opaque_ptr->m_rsync_remote_path_prefix.clear();
+
+ if (options && options[0])
+ m_opaque_ptr->m_rsync_options = options;
+ else
+ m_opaque_ptr->m_rsync_options.clear();
+
+}
+
+void
+SBPlatformConnectOptions::DisableRsync ()
+{
+ m_opaque_ptr->m_rsync_enabled = false;
+}
+
+const char *
+SBPlatformConnectOptions::GetLocalCacheDirectory()
+{
+ return m_opaque_ptr->m_local_cache_directory.GetCString();
+}
+
+void
+SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path)
+{
+ if (path && path[0])
+ m_opaque_ptr->m_local_cache_directory.SetCString(path);
+ else
+ m_opaque_ptr->m_local_cache_directory = ConstString();
+}
+
+//----------------------------------------------------------------------
+// SBPlatformShellCommand
+//----------------------------------------------------------------------
+SBPlatformShellCommand::SBPlatformShellCommand (const char *shell_command) :
+ m_opaque_ptr(new PlatformShellCommand(shell_command))
+{
+}
+
+SBPlatformShellCommand::SBPlatformShellCommand (const SBPlatformShellCommand &rhs) :
+ m_opaque_ptr(new PlatformShellCommand())
+{
+ *m_opaque_ptr = *rhs.m_opaque_ptr;
+}
+
+SBPlatformShellCommand::~SBPlatformShellCommand()
+{
+ delete m_opaque_ptr;
+}
+
+void
+SBPlatformShellCommand::Clear()
+{
+ m_opaque_ptr->m_output = std::move(std::string());
+ m_opaque_ptr->m_status = 0;
+ m_opaque_ptr->m_signo = 0;
+}
+
+const char *
+SBPlatformShellCommand::GetCommand()
+{
+ if (m_opaque_ptr->m_command.empty())
+ return NULL;
+ return m_opaque_ptr->m_command.c_str();
+}
+
+void
+SBPlatformShellCommand::SetCommand(const char *shell_command)
+{
+ if (shell_command && shell_command[0])
+ m_opaque_ptr->m_command = shell_command;
+ else
+ m_opaque_ptr->m_command.clear();
+}
+
+const char *
+SBPlatformShellCommand::GetWorkingDirectory ()
+{
+ if (m_opaque_ptr->m_working_dir.empty())
+ return NULL;
+ return m_opaque_ptr->m_working_dir.c_str();
+}
+
+void
+SBPlatformShellCommand::SetWorkingDirectory (const char *path)
+{
+ if (path && path[0])
+ m_opaque_ptr->m_working_dir = path;
+ else
+ m_opaque_ptr->m_working_dir.clear();
+}
+
+uint32_t
+SBPlatformShellCommand::GetTimeoutSeconds ()
+{
+ return m_opaque_ptr->m_timeout_sec;
+}
+
+void
+SBPlatformShellCommand::SetTimeoutSeconds (uint32_t sec)
+{
+ m_opaque_ptr->m_timeout_sec = sec;
+}
+
+int
+SBPlatformShellCommand::GetSignal ()
+{
+ return m_opaque_ptr->m_signo;
+}
+
+int
+SBPlatformShellCommand::GetStatus ()
+{
+ return m_opaque_ptr->m_status;
+}
+
+const char *
+SBPlatformShellCommand::GetOutput ()
+{
+ if (m_opaque_ptr->m_output.empty())
+ return NULL;
+ return m_opaque_ptr->m_output.c_str();
+}
+
+//----------------------------------------------------------------------
+// SBPlatform
+//----------------------------------------------------------------------
+SBPlatform::SBPlatform () :
+ m_opaque_sp ()
+{
+
+}
+
+SBPlatform::SBPlatform (const char *platform_name) :
+ m_opaque_sp ()
+{
+ Error error;
+ m_opaque_sp = Platform::Create (platform_name, error);
+}
+
+SBPlatform::~SBPlatform()
+{
+}
+
+bool
+SBPlatform::IsValid () const
+{
+ return m_opaque_sp.get() != NULL;
+}
+
+void
+SBPlatform::Clear ()
+{
+ m_opaque_sp.reset();
+}
+
+const char *
+SBPlatform::GetName ()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ return platform_sp->GetName().GetCString();
+ return NULL;
+}
+
+lldb::PlatformSP
+SBPlatform::GetSP () const
+{
+ return m_opaque_sp;
+}
+
+void
+SBPlatform::SetSP (const lldb::PlatformSP& platform_sp)
+{
+ m_opaque_sp = platform_sp;
+}
+
+const char *
+SBPlatform::GetWorkingDirectory()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ return platform_sp->GetWorkingDirectory().GetCString();
+ return NULL;
+}
+
+bool
+SBPlatform::SetWorkingDirectory(const char *path)
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ if (path)
+ platform_sp->SetWorkingDirectory(ConstString(path));
+ else
+ platform_sp->SetWorkingDirectory(ConstString());
+ return true;
+ }
+ return false;
+}
+
+SBError
+SBPlatform::ConnectRemote (SBPlatformConnectOptions &connect_options)
+{
+ SBError sb_error;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp && connect_options.GetURL())
+ {
+ Args args;
+ args.AppendArgument(connect_options.GetURL());
+ sb_error.ref() = platform_sp->ConnectRemote(args);
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid platform");
+ }
+ return sb_error;
+}
+
+void
+SBPlatform::DisconnectRemote ()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ platform_sp->DisconnectRemote();
+}
+
+bool
+SBPlatform::IsConnected()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ platform_sp->IsConnected();
+ return false;
+}
+
+const char *
+SBPlatform::GetTriple()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ ArchSpec arch(platform_sp->GetRemoteSystemArchitecture());
+ if (arch.IsValid())
+ {
+ // Const-ify the string so we don't need to worry about the lifetime of the string
+ return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
+ }
+ }
+ return NULL;
+}
+
+const char *
+SBPlatform::GetOSBuild()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ std::string s;
+ if (platform_sp->GetOSBuildString(s))
+ {
+ if (!s.empty())
+ {
+ // Const-ify the string so we don't need to worry about the lifetime of the string
+ return ConstString(s.c_str()).GetCString();
+ }
+ }
+ }
+ return NULL;
+}
+
+const char *
+SBPlatform::GetOSDescription()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ std::string s;
+ if (platform_sp->GetOSKernelDescription(s))
+ {
+ if (!s.empty())
+ {
+ // Const-ify the string so we don't need to worry about the lifetime of the string
+ return ConstString(s.c_str()).GetCString();
+ }
+ }
+ }
+ return NULL;
+}
+
+const char *
+SBPlatform::GetHostname ()
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ return platform_sp->GetHostname();
+ return NULL;
+}
+
+uint32_t
+SBPlatform::GetOSMajorVersion ()
+{
+ uint32_t major, minor, update;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
+ return major;
+ return UINT32_MAX;
+
+}
+
+uint32_t
+SBPlatform::GetOSMinorVersion ()
+{
+ uint32_t major, minor, update;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
+ return minor;
+ return UINT32_MAX;
+}
+
+uint32_t
+SBPlatform::GetOSUpdateVersion ()
+{
+ uint32_t major, minor, update;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp && platform_sp->GetOSVersion(major, minor, update))
+ return update;
+ return UINT32_MAX;
+}
+
+SBError
+SBPlatform::Get (SBFileSpec &src,
+ SBFileSpec &dst)
+{
+ SBError sb_error;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid platform");
+ }
+ return sb_error;
+}
+
+SBError
+SBPlatform::Put (SBFileSpec &src,
+ SBFileSpec &dst)
+{
+ SBError sb_error;
+
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ if (src.Exists())
+ {
+ uint32_t permissions = src.ref().GetPermissions();
+ if (permissions == 0)
+ {
+ if (src.ref().GetFileType() == FileSpec::eFileTypeDirectory)
+ permissions = eFilePermissionsDirectoryDefault;
+ else
+ permissions = eFilePermissionsFileDefault;
+ }
+
+ sb_error.ref() = platform_sp->PutFile(src.ref(),
+ dst.ref(),
+ permissions);
+ }
+ else
+ {
+ sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
+ }
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid platform");
+ }
+ return sb_error;
+}
+
+SBError
+SBPlatform::Install (SBFileSpec &src,
+ SBFileSpec &dst)
+{
+ SBError sb_error;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ if (src.Exists())
+ {
+ sb_error.ref() = platform_sp->Install(src.ref(), dst.ref());
+ }
+ else
+ {
+ sb_error.ref().SetErrorStringWithFormat("'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
+ }
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid platform");
+ }
+ return sb_error;
+}
+
+
+SBError
+SBPlatform::Run (SBPlatformShellCommand &shell_command)
+{
+ SBError sb_error;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ if (platform_sp->IsConnected())
+ {
+ const char *command = shell_command.GetCommand();
+ if (command)
+ {
+ const char *working_dir = shell_command.GetWorkingDirectory();
+ if (working_dir == NULL)
+ {
+ working_dir = platform_sp->GetWorkingDirectory().GetCString();
+ if (working_dir)
+ shell_command.SetWorkingDirectory(working_dir);
+ }
+ sb_error.ref() = platform_sp->RunShellCommand(command,
+ working_dir,
+ &shell_command.m_opaque_ptr->m_status,
+ &shell_command.m_opaque_ptr->m_signo,
+ &shell_command.m_opaque_ptr->m_output,
+ shell_command.m_opaque_ptr->m_timeout_sec);
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid shell command (empty)");
+ }
+ }
+ else
+ {
+ sb_error.SetErrorString("not connected");
+ }
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid platform");
+ }
+ return sb_error;
+}
+
+SBError
+SBPlatform::MakeDirectory (const char *path, uint32_t file_permissions)
+{
+ SBError sb_error;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ sb_error.ref() = platform_sp->MakeDirectory(path, file_permissions);
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid platform");
+ }
+ return sb_error;
+}
+
+uint32_t
+SBPlatform::GetFilePermissions (const char *path)
+{
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ uint32_t file_permissions = 0;
+ platform_sp->GetFilePermissions(path, file_permissions);
+ return file_permissions;
+ }
+ return 0;
+
+}
+
+SBError
+SBPlatform::SetFilePermissions (const char *path, uint32_t file_permissions)
+{
+ SBError sb_error;
+ PlatformSP platform_sp(GetSP());
+ if (platform_sp)
+ {
+ sb_error.ref() = platform_sp->SetFilePermissions(path, file_permissions);
+ }
+ else
+ {
+ sb_error.SetErrorString("invalid platform");
+ }
+ return sb_error;
+
+}
+
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index d690da7eed87..557006f24345 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -1278,7 +1278,7 @@ SBProcess::GetExtendedBacktraceTypeAtIndex (uint32_t idx)
if (process_sp && process_sp->GetSystemRuntime())
{
SystemRuntime *runtime = process_sp->GetSystemRuntime();
- std::vector<ConstString> names = runtime->GetExtendedBacktraceTypes();
+ const std::vector<ConstString> &names = runtime->GetExtendedBacktraceTypes();
if (idx < names.size())
{
return names[idx].AsCString();
diff --git a/source/API/SBStream.cpp b/source/API/SBStream.cpp
index dc8eb05ab0ba..531ab9f463ce 100644
--- a/source/API/SBStream.cpp
+++ b/source/API/SBStream.cpp
@@ -82,7 +82,7 @@ SBStream::RedirectToFile (const char *path, bool append)
uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
if (append)
open_options |= File::eOpenOptionAppend;
- stream_file->GetFile().Open (path, open_options, File::ePermissionsDefault);
+ stream_file->GetFile().Open (path, open_options, lldb::eFilePermissionsFileDefault);
m_opaque_ap.reset (stream_file);
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index cff6e4e2de36..c8bc2171436d 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -605,6 +605,19 @@ SBTarget::LaunchSimple
error);
}
+SBError
+SBTarget::Install()
+{
+ SBError sb_error;
+ TargetSP target_sp(GetSP());
+ if (target_sp)
+ {
+ Mutex::Locker api_locker (target_sp->GetAPIMutex());
+ sb_error.ref() = target_sp->Install(NULL);
+ }
+ return sb_error;
+}
+
SBProcess
SBTarget::Launch
(
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index 4b54b1c0c1c6..4170d5b230bb 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -433,7 +433,6 @@ SBThread::SetThread (const ThreadSP& lldb_object_sp)
m_opaque_sp->SetThreadSP (lldb_object_sp);
}
-
lldb::tid_t
SBThread::GetThreadID () const
{
@@ -1283,7 +1282,7 @@ SBThread::GetDescription (SBStream &description) const
}
SBThread
-SBThread::GetExtendedBacktrace (const char *type)
+SBThread::GetExtendedBacktraceThread (const char *type)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
Mutex::Locker api_locker;
@@ -1295,24 +1294,50 @@ SBThread::GetExtendedBacktrace (const char *type)
Process::StopLocker stop_locker;
if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock()))
{
- ThreadSP real_thread(exe_ctx.GetThreadPtr());
+ ThreadSP real_thread(exe_ctx.GetThreadSP());
if (real_thread)
{
ConstString type_const (type);
- SystemRuntime *runtime = exe_ctx.GetProcessPtr()->GetSystemRuntime();
- if (runtime)
+ Process *process = exe_ctx.GetProcessPtr();
+ if (process)
{
- ThreadSP origin_thread = runtime->GetExtendedBacktrace (real_thread, type_const);
- sb_origin_thread.SetThread (origin_thread);
+ SystemRuntime *runtime = process->GetSystemRuntime();
+ if (runtime)
+ {
+ ThreadSP new_thread_sp (runtime->GetExtendedBacktraceThread (real_thread, type_const));
+ if (new_thread_sp)
+ {
+ // Save this in the Process' ExtendedThreadList so a strong pointer retains the
+ // object.
+ process->GetExtendedThreadList().AddThread (new_thread_sp);
+ sb_origin_thread.SetThread (new_thread_sp);
+ if (log)
+ {
+ const char *queue_name = new_thread_sp->GetQueueName();
+ if (queue_name == NULL)
+ queue_name = "";
+ log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => new extended Thread created (%p) with queue_id 0x%" PRIx64 " queue name '%s'", exe_ctx.GetThreadPtr(), new_thread_sp.get(), new_thread_sp->GetQueueID(), queue_name);
+ }
+ }
+ }
}
}
}
else
{
if (log)
- log->Printf ("SBThread(%p)::GetExtendedBacktrace() => error: process is running", exe_ctx.GetThreadPtr());
+ log->Printf ("SBThread(%p)::GetExtendedBacktraceThread() => error: process is running", exe_ctx.GetThreadPtr());
}
}
return sb_origin_thread;
}
+
+uint32_t
+SBThread::GetExtendedBacktraceOriginatingIndexID ()
+{
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (thread_sp)
+ return thread_sp->GetExtendedBacktraceOriginatingIndexID();
+ return LLDB_INVALID_INDEX32;
+}
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp
index e07205e360b1..32c0b1066f8e 100644
--- a/source/Breakpoint/Breakpoint.cpp
+++ b/source/Breakpoint/Breakpoint.cpp
@@ -114,6 +114,12 @@ Breakpoint::GetLocationAtIndex (size_t index)
return m_locations.GetByIndex(index);
}
+void
+Breakpoint::RemoveInvalidLocations (const ArchSpec &arch)
+{
+ m_locations.RemoveInvalidLocations(arch);
+}
+
// For each of the overall options we need to decide how they propagate to
// the location options. This will determine the precedence of options on
// the breakpoint vs. its locations.
diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp
index c6030d60ca04..147ad36b0407 100644
--- a/source/Breakpoint/BreakpointList.cpp
+++ b/source/Breakpoint/BreakpointList.cpp
@@ -69,12 +69,20 @@ BreakpointList::Remove (break_id_t break_id, bool notify)
}
void
+BreakpointList::RemoveInvalidLocations (const ArchSpec &arch)
+{
+ Mutex::Locker locker(m_mutex);
+ for (const auto &bp_sp : m_breakpoints)
+ bp_sp->RemoveInvalidLocations(arch);
+}
+
+
+void
BreakpointList::SetEnabledAll (bool enabled)
{
Mutex::Locker locker(m_mutex);
- bp_collection::iterator pos, end = m_breakpoints.end();
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- (*pos)->SetEnabled (enabled);
+ for (const auto &bp_sp : m_breakpoints)
+ bp_sp->SetEnabled (enabled);
}
@@ -163,10 +171,8 @@ BreakpointList::Dump (Stream *s) const
s->Indent();
s->Printf("BreakpointList with %u Breakpoints:\n", (uint32_t)m_breakpoints.size());
s->IndentMore();
- bp_collection::const_iterator pos;
- bp_collection::const_iterator end = m_breakpoints.end();
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- (*pos)->Dump(s);
+ for (const auto &bp_sp : m_breakpoints)
+ bp_sp->Dump(s);
s->IndentLess();
}
@@ -207,10 +213,8 @@ void
BreakpointList::UpdateBreakpoints (ModuleList& module_list, bool added, bool delete_locations)
{
Mutex::Locker locker(m_mutex);
- bp_collection::iterator end = m_breakpoints.end();
- bp_collection::iterator pos;
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- (*pos)->ModulesChanged (module_list, added, delete_locations);
+ for (const auto &bp_sp : m_breakpoints)
+ bp_sp->ModulesChanged (module_list, added, delete_locations);
}
@@ -218,10 +222,8 @@ void
BreakpointList::UpdateBreakpointsWhenModuleIsReplaced (ModuleSP old_module_sp, ModuleSP new_module_sp)
{
Mutex::Locker locker(m_mutex);
- bp_collection::iterator end = m_breakpoints.end();
- bp_collection::iterator pos;
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- (*pos)->ModuleReplaced (old_module_sp, new_module_sp);
+ for (const auto &bp_sp : m_breakpoints)
+ bp_sp->ModuleReplaced (old_module_sp, new_module_sp);
}
@@ -229,10 +231,8 @@ void
BreakpointList::ClearAllBreakpointSites ()
{
Mutex::Locker locker(m_mutex);
- bp_collection::iterator end = m_breakpoints.end();
- bp_collection::iterator pos;
- for (pos = m_breakpoints.begin(); pos != end; ++pos)
- (*pos)->ClearAllBreakpointSites ();
+ for (const auto &bp_sp : m_breakpoints)
+ bp_sp->ClearAllBreakpointSites ();
}
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
index 17568c28b507..5009e862d84b 100644
--- a/source/Breakpoint/BreakpointLocation.cpp
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -295,7 +295,7 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
options.SetIgnoreBreakpoints(true);
- options.SetRunOthers(true);
+ options.SetTryAllThreads(true);
Error expr_error;
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp
index 341b09716301..0c4c54d2f16c 100644
--- a/source/Breakpoint/BreakpointLocationList.cpp
+++ b/source/Breakpoint/BreakpointLocationList.cpp
@@ -13,8 +13,11 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocationList.h"
+
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Target/Target.h"
@@ -74,19 +77,25 @@ BreakpointLocationList::FindIDByAddress (const Address &addr)
return LLDB_INVALID_BREAK_ID;
}
+static bool
+Compare (BreakpointLocationSP lhs, lldb::break_id_t val)
+{
+ return lhs->GetID() < val;
+}
+
BreakpointLocationSP
BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
{
BreakpointLocationSP bp_loc_sp;
Mutex::Locker locker (m_mutex);
- // We never remove a breakpoint locations, so the ID can be translated into
- // the location index by subtracting 1
- uint32_t idx = break_id - 1;
- if (idx <= m_locations.size())
- {
- bp_loc_sp = m_locations[idx];
- }
- return bp_loc_sp;
+
+ collection::const_iterator begin = m_locations.begin(), end = m_locations.end();
+ collection::const_iterator result;
+ result = std::lower_bound(begin, end, break_id, Compare);
+ if (result == end)
+ return bp_loc_sp;
+ else
+ return *(result);
}
size_t
@@ -286,7 +295,41 @@ BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc
return false;
}
-
+void
+BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch)
+{
+ Mutex::Locker locker (m_mutex);
+ size_t idx = 0;
+ // Don't cache m_location.size() as it will change since we might
+ // remove locations from our vector...
+ while (idx < m_locations.size())
+ {
+ BreakpointLocation *bp_loc = m_locations[idx].get();
+ if (bp_loc->GetAddress().SectionWasDeleted())
+ {
+ // Section was deleted which means this breakpoint comes from a module
+ // that is no longer valid, so we should remove it.
+ m_locations.erase(m_locations.begin() + idx);
+ continue;
+ }
+ if (arch.IsValid())
+ {
+ ModuleSP module_sp (bp_loc->GetAddress().GetModule());
+ if (module_sp)
+ {
+ if (!arch.IsCompatibleMatch(module_sp->GetArchitecture()))
+ {
+ // The breakpoint was in a module whose architecture is no longer
+ // compatible with "arch", so we need to remove it
+ m_locations.erase(m_locations.begin() + idx);
+ continue;
+ }
+ }
+ }
+ // Only increment the index if we didn't remove the locations at index "idx"
+ ++idx;
+ }
+}
void
BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index 6d44f71b8d95..5ca44ff920d6 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -363,13 +363,13 @@ CommandObjectExpression::EvaluateExpression
bool keep_in_memory = true;
EvaluateExpressionOptions options;
- options.SetCoerceToId(m_varobj_options.use_objc)
- .SetUnwindOnError(m_command_options.unwind_on_error)
- .SetIgnoreBreakpoints (m_command_options.ignore_breakpoints)
- .SetKeepInMemory(keep_in_memory)
- .SetUseDynamic(m_varobj_options.use_dynamic)
- .SetRunOthers(m_command_options.try_all_threads)
- .SetDebug(m_command_options.debug);
+ options.SetCoerceToId(m_varobj_options.use_objc);
+ options.SetUnwindOnError(m_command_options.unwind_on_error);
+ options.SetIgnoreBreakpoints (m_command_options.ignore_breakpoints);
+ options.SetKeepInMemory(keep_in_memory);
+ options.SetUseDynamic(m_varobj_options.use_dynamic);
+ options.SetTryAllThreads(m_command_options.try_all_threads);
+ options.SetDebug(m_command_options.debug);
if (m_command_options.timeout > 0)
options.SetTimeoutUsec(m_command_options.timeout);
diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp
index 2ee275e11f66..cb7398fb9554 100644
--- a/source/Commands/CommandObjectMemory.cpp
+++ b/source/Commands/CommandObjectMemory.cpp
@@ -914,6 +914,311 @@ protected:
ClangASTType m_prev_clang_ast_type;
};
+OptionDefinition
+g_memory_find_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
+ { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
+ { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many times to perform the search."},
+ { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
+};
+
+//----------------------------------------------------------------------
+// Find the specified data in memory
+//----------------------------------------------------------------------
+class CommandObjectMemoryFind : public CommandObjectParsed
+{
+public:
+
+ class OptionGroupFindMemory : public OptionGroup
+ {
+ public:
+ OptionGroupFindMemory () :
+ OptionGroup(),
+ m_count(1),
+ m_offset(0)
+ {
+ }
+
+ virtual
+ ~OptionGroupFindMemory ()
+ {
+ }
+
+ virtual uint32_t
+ GetNumDefinitions ()
+ {
+ return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
+ }
+
+ virtual const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_memory_find_option_table;
+ }
+
+ virtual Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_arg)
+ {
+ Error error;
+ const int short_option = g_memory_find_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'e':
+ m_expr.SetValueFromCString(option_arg);
+ break;
+
+ case 's':
+ m_string.SetValueFromCString(option_arg);
+ break;
+
+ case 'c':
+ if (m_count.SetValueFromCString(option_arg).Fail())
+ error.SetErrorString("unrecognized value for count");
+ break;
+
+ case 'o':
+ if (m_offset.SetValueFromCString(option_arg).Fail())
+ error.SetErrorString("unrecognized value for dump-offset");
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
+ break;
+ }
+ return error;
+ }
+
+ virtual void
+ OptionParsingStarting (CommandInterpreter &interpreter)
+ {
+ m_expr.Clear();
+ m_string.Clear();
+ m_count.Clear();
+ }
+
+ OptionValueString m_expr;
+ OptionValueString m_string;
+ OptionValueUInt64 m_count;
+ OptionValueUInt64 m_offset;
+ };
+
+ CommandObjectMemoryFind (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "memory find",
+ "Find a value in the memory of the process being debugged.",
+ NULL,
+ eFlagRequiresProcess | eFlagProcessMustBeLaunched),
+ m_option_group (interpreter),
+ m_memory_options ()
+ {
+ CommandArgumentEntry arg1;
+ CommandArgumentEntry arg2;
+ CommandArgumentData addr_arg;
+ CommandArgumentData value_arg;
+
+ // Define the first (and only) variant of this arg.
+ addr_arg.arg_type = eArgTypeAddress;
+ addr_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg1.push_back (addr_arg);
+
+ // Define the first (and only) variant of this arg.
+ value_arg.arg_type = eArgTypeValue;
+ value_arg.arg_repetition = eArgRepeatPlus;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg2.push_back (value_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg1);
+ m_arguments.push_back (arg2);
+
+ m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
+ m_option_group.Finalize();
+ }
+
+ virtual
+ ~CommandObjectMemoryFind ()
+ {
+ }
+
+ Options *
+ GetOptions ()
+ {
+ return &m_option_group;
+ }
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
+ Process *process = m_exe_ctx.GetProcessPtr();
+
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc != 2)
+ {
+ result.AppendError("two addresses needed for memory find");
+ return false;
+ }
+
+ Error error;
+ lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
+ if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
+ {
+ result.AppendError("invalid low address");
+ return false;
+ }
+ lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
+ if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
+ {
+ result.AppendError("invalid low address");
+ return false;
+ }
+
+ if (high_addr <= low_addr)
+ {
+ result.AppendError("starting address must be smaller than ending address");
+ return false;
+ }
+
+ lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
+
+ DataBufferHeap buffer;
+
+ if (m_memory_options.m_string.OptionWasSet())
+ buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
+ else if (m_memory_options.m_expr.OptionWasSet())
+ {
+ StackFrame* frame = m_exe_ctx.GetFramePtr();
+ ValueObjectSP result_sp;
+ if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
+ {
+ uint64_t value = result_sp->GetValueAsUnsigned(0);
+ switch (result_sp->GetClangType().GetByteSize())
+ {
+ case 1: {
+ uint8_t byte = (uint8_t)value;
+ buffer.CopyData(&byte,1);
+ }
+ break;
+ case 2: {
+ uint16_t word = (uint16_t)value;
+ buffer.CopyData(&word,2);
+ }
+ break;
+ case 4: {
+ uint32_t lword = (uint32_t)value;
+ buffer.CopyData(&lword,4);
+ }
+ break;
+ case 8: {
+ buffer.CopyData(&value, 8);
+ }
+ break;
+ case 3:
+ case 5:
+ case 6:
+ case 7:
+ result.AppendError("unknown type. pass a string instead");
+ return false;
+ default:
+ result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
+ return false;
+ }
+ }
+ else
+ {
+ result.AppendError("expression evaluation failed. pass a string instead?");
+ return false;
+ }
+ }
+ else
+ {
+ result.AppendError("please pass either a block of text, or an expression to evaluate.");
+ return false;
+ }
+
+ size_t count = m_memory_options.m_count.GetCurrentValue();
+ found_location = low_addr;
+ bool ever_found = false;
+ while (count)
+ {
+ found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
+ if (found_location == LLDB_INVALID_ADDRESS)
+ {
+ if (!ever_found)
+ {
+ result.AppendMessage("Your data was not found within the range.\n");
+ result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ result.AppendMessage("No more matches found within the range.\n");
+ break;
+ }
+ result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
+
+ DataBufferHeap dumpbuffer(32,0);
+ process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
+ if (!error.Fail())
+ {
+ DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
+ data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
+ result.GetOutputStream().EOL();
+ }
+
+ --count;
+ found_location++;
+ ever_found = true;
+ }
+
+ result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+ lldb::addr_t
+ Search (lldb::addr_t low,
+ lldb::addr_t high,
+ uint8_t* buffer,
+ size_t buffer_size)
+ {
+ Process *process = m_exe_ctx.GetProcessPtr();
+ DataBufferHeap heap(buffer_size, 0);
+ lldb::addr_t fictional_ptr = low;
+ for (auto ptr = low;
+ low < high;
+ fictional_ptr++)
+ {
+ Error error;
+ if (ptr == low || buffer_size == 1)
+ process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
+ else
+ {
+ memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
+ process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
+ }
+ if (error.Fail())
+ return LLDB_INVALID_ADDRESS;
+ if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
+ return fictional_ptr;
+ if (ptr == low)
+ ptr += buffer_size;
+ else
+ ptr += 1;
+ }
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ OptionGroupOptions m_option_group;
+ OptionGroupFindMemory m_memory_options;
+};
+
OptionDefinition
g_memory_write_option_table[] =
@@ -922,7 +1227,6 @@ g_memory_write_option_table[] =
{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
};
-
//----------------------------------------------------------------------
// Write memory to the inferior process
//----------------------------------------------------------------------
@@ -948,13 +1252,13 @@ public:
{
return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
}
-
+
virtual const OptionDefinition*
GetDefinitions ()
{
return g_memory_write_option_table;
}
-
+
virtual Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
@@ -962,7 +1266,7 @@ public:
{
Error error;
const int short_option = g_memory_write_option_table[option_idx].short_option;
-
+
switch (short_option)
{
case 'i':
@@ -973,7 +1277,7 @@ public:
error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
}
break;
-
+
case 'o':
{
bool success;
@@ -1374,6 +1678,7 @@ CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
"A set of commands for operating on memory.",
"memory <subcommand> [<subcommand-options>]")
{
+ LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
}
diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp
index ace1ef5b53fb..5e842bf848a3 100644
--- a/source/Commands/CommandObjectPlatform.cpp
+++ b/source/Commands/CommandObjectPlatform.cpp
@@ -22,6 +22,7 @@
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionGroupFile.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
@@ -119,31 +120,31 @@ public:
m_permissions = perms;
}
case 'r':
- m_permissions |= File::ePermissionsUserRead;
+ m_permissions |= lldb::eFilePermissionsUserRead;
break;
case 'w':
- m_permissions |= File::ePermissionsUserWrite;
+ m_permissions |= lldb::eFilePermissionsUserWrite;
break;
case 'x':
- m_permissions |= File::ePermissionsUserExecute;
+ m_permissions |= lldb::eFilePermissionsUserExecute;
break;
case 'R':
- m_permissions |= File::ePermissionsGroupRead;
+ m_permissions |= lldb::eFilePermissionsGroupRead;
break;
case 'W':
- m_permissions |= File::ePermissionsGroupWrite;
+ m_permissions |= lldb::eFilePermissionsGroupWrite;
break;
case 'X':
- m_permissions |= File::ePermissionsGroupExecute;
+ m_permissions |= lldb::eFilePermissionsGroupExecute;
break;
case 'd':
- m_permissions |= File::ePermissionsWorldRead;
+ m_permissions |= lldb::eFilePermissionsWorldRead;
break;
case 't':
- m_permissions |= File::ePermissionsWorldWrite;
+ m_permissions |= lldb::eFilePermissionsWorldWrite;
break;
case 'e':
- m_permissions |= File::ePermissionsWorldExecute;
+ m_permissions |= lldb::eFilePermissionsWorldExecute;
break;
default:
@@ -524,6 +525,65 @@ protected:
};
//----------------------------------------------------------------------
+// "platform settings"
+//----------------------------------------------------------------------
+class CommandObjectPlatformSettings : public CommandObjectParsed
+{
+public:
+ CommandObjectPlatformSettings (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "platform settings",
+ "Set settings for the current target's platform, or for a platform by name.",
+ "platform settings",
+ 0),
+ m_options (interpreter),
+ m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.")
+ {
+ m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ }
+
+ virtual
+ ~CommandObjectPlatformSettings ()
+ {
+ }
+
+protected:
+ virtual bool
+ DoExecute (Args& args, CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ if (platform_sp)
+ {
+ if (m_option_working_dir.GetOptionValue().OptionWasSet())
+ platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str()));
+ }
+ else
+ {
+ result.AppendError ("no platform is currently selected");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+
+ virtual Options *
+ GetOptions ()
+ {
+ if (m_options.DidFinalize() == false)
+ {
+ m_options.Append(new OptionPermissions());
+ m_options.Finalize();
+ }
+ return &m_options;
+ }
+protected:
+
+ OptionGroupOptions m_options;
+ OptionGroupFile m_option_working_dir;
+
+};
+
+
+//----------------------------------------------------------------------
// "platform mkdir"
//----------------------------------------------------------------------
class CommandObjectPlatformMkDir : public CommandObjectParsed
@@ -552,15 +612,22 @@ public:
{
std::string cmd_line;
args.GetCommandString(cmd_line);
- mode_t perms;
+ uint32_t mode;
const OptionPermissions* options_permissions = (OptionPermissions*)m_options.GetGroupWithOption('r');
if (options_permissions)
- perms = options_permissions->m_permissions;
+ mode = options_permissions->m_permissions;
else
- perms = 0000700 | 0000070 | 0000007;
- uint32_t retcode = platform_sp->MakeDirectory(cmd_line,perms);
- result.AppendMessageWithFormat("Status = %d\n",retcode);
- result.SetStatus (eReturnStatusSuccessFinishResult);
+ mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX;
+ Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode);
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError(error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
}
else
{
@@ -619,7 +686,7 @@ public:
if (options_permissions)
perms = options_permissions->m_permissions;
else
- perms = 0000700 | 0000070 | 0000007;
+ perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead;
lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false),
File::eOpenOptionRead | File::eOpenOptionWrite |
File::eOpenOptionAppend | File::eOpenOptionCanCreate,
@@ -2129,82 +2196,6 @@ CommandObjectPlatformShell::CommandOptions::g_option_table[] =
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
-struct RecurseCopyBaton
-{
- const std::string& destination;
- const PlatformSP& platform_sp;
- Error error;
-};
-
-
-static FileSpec::EnumerateDirectoryResult
-RecurseCopy_Callback (void *baton,
- FileSpec::FileType file_type,
- const FileSpec &spec)
-{
- RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
- switch (file_type)
- {
- case FileSpec::eFileTypePipe:
- case FileSpec::eFileTypeSocket:
- // we have no way to copy pipes and sockets - ignore them and continue
- return FileSpec::eEnumerateDirectoryResultNext;
- break;
-
- case FileSpec::eFileTypeSymbolicLink:
- // what to do for symlinks?
- return FileSpec::eEnumerateDirectoryResultNext;
- break;
-
- case FileSpec::eFileTypeDirectory:
- {
- // make the new directory and get in there
- FileSpec new_directory(rc_baton->destination.c_str(),false);
- new_directory.AppendPathComponent(spec.GetLastPathComponent());
- uint32_t errcode = rc_baton->platform_sp->MakeDirectory(new_directory, 0777);
- std::string new_directory_path (new_directory.GetPath());
- if (errcode != 0)
- {
- rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end",new_directory_path.c_str());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
- }
-
- // now recurse
- std::string local_path (spec.GetPath());
- RecurseCopyBaton rc_baton2 = { new_directory_path, rc_baton->platform_sp, Error() };
- FileSpec::EnumerateDirectory(local_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
- if (rc_baton2.error.Fail())
- {
- rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
- }
- return FileSpec::eEnumerateDirectoryResultNext;
- }
- break;
-
- case FileSpec::eFileTypeRegular:
- {
- // copy the file and keep going
- std::string dest(rc_baton->destination);
- dest.append(spec.GetFilename().GetCString());
- Error err = rc_baton->platform_sp->PutFile(spec, FileSpec(dest.c_str(), false));
- if (err.Fail())
- {
- rc_baton->error.SetErrorString(err.AsCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
- }
- return FileSpec::eEnumerateDirectoryResultNext;
- }
- break;
-
- case FileSpec::eFileTypeInvalid:
- case FileSpec::eFileTypeOther:
- case FileSpec::eFileTypeUnknown:
- rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s/%s", spec.GetDirectory().GetCString(), spec.GetFilename().GetCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
- break;
- }
-}
//----------------------------------------------------------------------
// "platform install" - install a target to a remote end
@@ -2236,10 +2227,9 @@ public:
return false;
}
// TODO: move the bulk of this code over to the platform itself
- std::string local_thing(args.GetArgumentAtIndex(0));
- std::string remote_sandbox(args.GetArgumentAtIndex(1));
- FileSpec source(local_thing.c_str(), true);
- if (source.Exists() == false)
+ FileSpec src(args.GetArgumentAtIndex(0), true);
+ FileSpec dst(args.GetArgumentAtIndex(1), false);
+ if (src.Exists() == false)
{
result.AppendError("source location does not exist or is not accessible");
result.SetStatus(eReturnStatusFailed);
@@ -2252,75 +2242,21 @@ public:
result.SetStatus (eReturnStatusFailed);
return false;
}
- FileSpec::FileType source_type(source.GetFileType());
- if (source_type == FileSpec::eFileTypeDirectory)
- {
- if (platform_sp->GetSupportsRSync())
- {
- FileSpec remote_folder(remote_sandbox.c_str(), false);
- Error rsync_err = platform_sp->PutFile(source, remote_folder);
- if (rsync_err.Success())
- {
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
- }
- FileSpec remote_folder(remote_sandbox.c_str(), false);
- remote_folder.AppendPathComponent(source.GetLastPathComponent());
- // TODO: default permissions are bad
- uint32_t errcode = platform_sp->MakeDirectory(remote_folder, 0777);
- if (errcode != 0)
- {
- result.AppendError("unable to setup target directory on remote end");
- result.SetStatus(eReturnStatusSuccessFinishNoResult);
- return result.Succeeded();
- }
- // now recurse
- std::string remote_folder_path (remote_folder.GetPath());
- Error err = RecurseCopy(source,remote_folder_path,platform_sp);
- if (err.Fail())
- {
- result.AppendError(err.AsCString());
- result.SetStatus(eReturnStatusFailed);
- }
- else
- result.SetStatus(eReturnStatusSuccessFinishResult);
- return result.Succeeded();
- }
- else if (source_type == FileSpec::eFileTypeRegular)
+
+ Error error = platform_sp->Install(src, dst);
+ if (error.Success())
{
- // just a plain file - push it to remote and be done
- remote_sandbox.append(source.GetFilename().GetCString());
- FileSpec destination(remote_sandbox.c_str(),false);
- Error err = platform_sp->PutFile(source, destination);
- if (err.Success())
- result.SetStatus(eReturnStatusSuccessFinishResult);
- else
- {
- result.AppendError(err.AsCString());
- result.SetStatus(eReturnStatusFailed);
- }
- return result.Succeeded();
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
}
else
{
- result.AppendError("source is not a known type of file");
+ result.AppendErrorWithFormat("install failed: %s", error.AsCString());
result.SetStatus(eReturnStatusFailed);
- return result.Succeeded();
}
+ return result.Succeeded();
}
private:
-
- Error
- RecurseCopy (const FileSpec& source,
- const std::string& destination,
- const PlatformSP& platform_sp)
- {
- std::string source_path (source.GetPath());
- RecurseCopyBaton baton = { destination, platform_sp, Error() };
- FileSpec::EnumerateDirectory(source_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
- return baton.error;
- }
+
};
//----------------------------------------------------------------------
@@ -2332,21 +2268,22 @@ CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
"A set of commands to manage and create platforms.",
"platform [connect|disconnect|info|list|status|select] ...")
{
- LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
- LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
- LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
- LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
- LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
+ LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
+ LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
+ LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
+ LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
+ LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
+ LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter)));
#ifdef LLDB_CONFIGURATION_DEBUG
- LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
- LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
- LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
- LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
- LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
+ LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
+ LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
+ LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
+ LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
+ LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
#endif
- LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
- LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
- LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
+ LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
+ LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
+ LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
}
diff --git a/source/Commands/CommandObjectPlugin.cpp b/source/Commands/CommandObjectPlugin.cpp
index 1bc7632e2985..658c077bc3ea 100644
--- a/source/Commands/CommandObjectPlugin.cpp
+++ b/source/Commands/CommandObjectPlugin.cpp
@@ -11,10 +11,6 @@
#include "CommandObjectPlugin.h"
-#include "lldb/API/SBDebugger.h"
-#include "lldb/API/SBCommandInterpreter.h"
-#include "lldb/API/SBCommandReturnObject.h"
-
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -79,8 +75,6 @@ protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
- typedef void (*LLDBCommandPluginInit) (lldb::SBDebugger debugger);
-
size_t argc = command.GetArgumentCount();
if (argc != 1)
diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp
index 8bdec6e4573a..2933c78ca908 100644
--- a/source/Commands/CommandObjectProcess.cpp
+++ b/source/Commands/CommandObjectProcess.cpp
@@ -251,9 +251,11 @@ protected:
// then you'll pick up that incorrect value.
bool synchronous_execution = m_interpreter.GetSynchronous ();
+ PlatformSP platform_sp (target->GetPlatform());
+
// Finalize the file actions, and if none were given, default to opening
// up a pseudo terminal
- const bool default_to_use_pty = true;
+ const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false;
m_options.launch_info.FinalizeFileActions (target, default_to_use_pty);
if (state == eStateConnected)
@@ -267,8 +269,6 @@ protected:
if (!m_options.launch_info.GetArchitecture().IsValid())
m_options.launch_info.GetArchitecture() = target->GetArchitecture();
-
- PlatformSP platform_sp (target->GetPlatform());
if (platform_sp && platform_sp->CanDebugProcess ())
{
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index ef431e25c3d4..8e7e68aad39a 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -1796,10 +1796,8 @@ LookupTypeInModule (CommandInterpreter &interpreter,
strm.Printf("%zu match%s found in ", num_matches, num_matches > 1 ? "es" : "");
DumpFullpath (strm, &module->GetFileSpec(), 0);
strm.PutCString(":\n");
- const uint32_t num_types = type_list.GetSize();
- for (uint32_t i=0; i<num_types; ++i)
+ for (TypeSP type_sp : type_list.Types())
{
- TypeSP type_sp (type_list.GetTypeAtIndex(i));
if (type_sp)
{
// Resolve the clang type so that any forward references
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index f46a2219a509..10d661882c92 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -28,6 +28,7 @@
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -92,6 +93,13 @@ public:
if (!success)
error.SetErrorStringWithFormat("invalid integer value for option '%c'", short_option);
}
+ case 'e':
+ {
+ bool success;
+ m_extended_backtrace = Args::StringToBoolean (option_arg, false, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid boolean value for option '%c'", short_option);
+ }
break;
default:
error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
@@ -106,6 +114,7 @@ public:
{
m_count = UINT32_MAX;
m_start = 0;
+ m_extended_backtrace = false;
}
const OptionDefinition*
@@ -121,6 +130,7 @@ public:
// Instance variables to hold the values for command options.
uint32_t m_count;
uint32_t m_start;
+ bool m_extended_backtrace;
};
CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
@@ -160,6 +170,32 @@ public:
}
protected:
+ void
+ DoExtendedBacktrace (Thread *thread, CommandReturnObject &result)
+ {
+ SystemRuntime *runtime = thread->GetProcess()->GetSystemRuntime();
+ if (runtime)
+ {
+ Stream &strm = result.GetOutputStream();
+ const std::vector<ConstString> &types = runtime->GetExtendedBacktraceTypes();
+ for (auto type : types)
+ {
+ ThreadSP ext_thread_sp = runtime->GetExtendedBacktraceThread (thread->shared_from_this(), type);
+ if (ext_thread_sp && ext_thread_sp->IsValid ())
+ {
+ const uint32_t num_frames_with_source = 0;
+ if (ext_thread_sp->GetStatus (strm,
+ m_options.m_start,
+ m_options.m_count,
+ num_frames_with_source))
+ {
+ DoExtendedBacktrace (ext_thread_sp.get(), result);
+ }
+ }
+ }
+ }
+ }
+
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
@@ -178,29 +214,36 @@ protected:
num_frames_with_source))
{
result.SetStatus (eReturnStatusSuccessFinishResult);
+ if (m_options.m_extended_backtrace)
+ {
+ DoExtendedBacktrace (thread, result);
+ }
}
}
else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
{
Process *process = m_exe_ctx.GetProcessPtr();
- Mutex::Locker locker (process->GetThreadList().GetMutex());
- uint32_t num_threads = process->GetThreadList().GetSize();
- for (uint32_t i = 0; i < num_threads; i++)
+ uint32_t idx = 0;
+ for (ThreadSP thread_sp : process->Threads())
{
- ThreadSP thread_sp = process->GetThreadList().GetThreadAtIndex(i);
+ if (idx != 0)
+ result.AppendMessage("");
+
if (!thread_sp->GetStatus (strm,
m_options.m_start,
m_options.m_count,
num_frames_with_source))
{
- result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", i);
+ result.AppendErrorWithFormat ("error displaying backtrace for thread: \"0x%4.4x\"\n", idx);
result.SetStatus (eReturnStatusFailed);
return false;
}
+ if (m_options.m_extended_backtrace)
+ {
+ DoExtendedBacktrace (thread_sp.get(), result);
+ }
- if (i < num_threads - 1)
- result.AppendMessage("");
-
+ ++idx;
}
}
else
@@ -244,6 +287,10 @@ protected:
result.SetStatus (eReturnStatusFailed);
return false;
}
+ if (m_options.m_extended_backtrace)
+ {
+ DoExtendedBacktrace (thread_sps[i].get(), result);
+ }
if (i < num_args - 1)
result.AppendMessage("");
@@ -260,6 +307,7 @@ CommandObjectThreadBacktrace::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many frames to display (-1 for all)"},
{ LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace"},
+{ LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Show the extended backtrace, if available"},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index ae490e38149e..e55b2ee4d7d8 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -939,7 +939,7 @@ public:
SetHelpLong(
"Examples: \n\
\n\
- watchpoint set variable -w read_wriate my_global_var \n\
+ watchpoint set variable -w read_write my_global_var \n\
# Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n");
CommandArgumentEntry arg;
@@ -1256,11 +1256,11 @@ protected:
// Use expression evaluation to arrive at the address to watch.
EvaluateExpressionOptions options;
- options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(false)
- .SetRunOthers(true)
- .SetTimeoutUsec(0);
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(false);
+ options.SetTryAllThreads(true);
+ options.SetTimeoutUsec(0);
ExecutionResults expr_result = target->EvaluateExpression (expr,
frame,
diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp
index 1e79f332ffc8..de2165cff84e 100644
--- a/source/Core/Address.cpp
+++ b/source/Core/Address.cpp
@@ -280,7 +280,7 @@ Address::GetFileAddress () const
// address by adding the file base address to our offset
return sect_file_addr + m_offset;
}
- else if (SectionWasDeleted())
+ else if (SectionWasDeletedPrivate())
{
// Used to have a valid section but it got deleted so the
// offset doesn't mean anything without the section
@@ -308,7 +308,7 @@ Address::GetLoadAddress (Target *target) const
}
}
}
- else if (SectionWasDeleted())
+ else if (SectionWasDeletedPrivate())
{
// Used to have a valid section but it got deleted so the
// offset doesn't mean anything without the section
@@ -783,6 +783,14 @@ Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, Dum
bool
Address::SectionWasDeleted() const
{
+ if (GetSection())
+ return false;
+ return SectionWasDeletedPrivate();
+}
+
+bool
+Address::SectionWasDeletedPrivate() const
+{
lldb::SectionWP empty_section_wp;
// If either call to "std::weak_ptr::owner_before(...) value returns true, this
diff --git a/source/Core/ConnectionFileDescriptor.cpp b/source/Core/ConnectionFileDescriptor.cpp
index 8e80543b857b..5764a212ab43 100644
--- a/source/Core/ConnectionFileDescriptor.cpp
+++ b/source/Core/ConnectionFileDescriptor.cpp
@@ -53,6 +53,8 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -1209,6 +1211,7 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
saddr_un.sun_len = SUN_LEN (&saddr_un);
#endif
+ Host::Unlink (socket_name);
if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
{
if (::listen (listen_socket, 5) == 0)
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index 3941d82d47b0..b57c6051a961 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -9,8 +9,6 @@
#include "lldb/lldb-python.h"
-#include "lldb/API/SBDebugger.h"
-
#include "lldb/Core/Debugger.h"
#include <map>
@@ -46,6 +44,7 @@
#include "lldb/Target/TargetList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -155,19 +154,7 @@ enum
ePropertyAutoOneLineSummaries
};
-//
-//const char *
-//Debugger::GetFrameFormat() const
-//{
-// return m_properties_sp->GetFrameFormat();
-//}
-//const char *
-//Debugger::GetThreadFormat() const
-//{
-// return m_properties_sp->GetThreadFormat();
-//}
-//
-
+Debugger::LoadPluginCallbackType Debugger::g_load_plugin_callback = NULL;
Error
Debugger::SetPropertyValue (const ExecutionContext *exe_ctx,
@@ -373,8 +360,9 @@ Debugger::TestDebuggerRefCount ()
}
void
-Debugger::Initialize ()
+Debugger::Initialize (LoadPluginCallbackType load_plugin_callback)
{
+ g_load_plugin_callback = load_plugin_callback;
if (g_shared_debugger_refcount++ == 0)
lldb_private::Initialize();
}
@@ -412,31 +400,22 @@ Debugger::SettingsTerminate ()
bool
Debugger::LoadPlugin (const FileSpec& spec, Error& error)
{
- lldb::DynamicLibrarySP dynlib_sp(new lldb_private::DynamicLibrary(spec));
- if (!dynlib_sp || dynlib_sp->IsValid() == false)
+ if (g_load_plugin_callback)
{
- if (spec.Exists())
- error.SetErrorString("this file does not represent a loadable dylib");
- else
- error.SetErrorString("no such file");
- return false;
- }
- lldb::DebuggerSP debugger_sp(shared_from_this());
- lldb::SBDebugger debugger_sb(debugger_sp);
- // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) function.
- // TODO: mangle this differently for your system - on OSX, the first underscore needs to be removed and the second one stays
- LLDBCommandPluginInit init_func = dynlib_sp->GetSymbol<LLDBCommandPluginInit>("_ZN4lldb16PluginInitializeENS_10SBDebuggerE");
- if (!init_func)
- {
- error.SetErrorString("cannot find the initialization function lldb::PluginInitialize(lldb::SBDebugger)");
- return false;
+ lldb::DynamicLibrarySP dynlib_sp = g_load_plugin_callback (shared_from_this(), spec, error);
+ if (dynlib_sp)
+ {
+ m_loaded_plugins.push_back(dynlib_sp);
+ return true;
+ }
}
- if (init_func(debugger_sb))
+ else
{
- m_loaded_plugins.push_back(dynlib_sp);
- return true;
+ // The g_load_plugin_callback is registered in SBDebugger::Initialize()
+ // and if the public API layer isn't available (code is linking against
+ // all of the internal LLDB static libraries), then we can't load plugins
+ error.SetErrorString("Public API layer is not available");
}
- error.SetErrorString("dylib refused to be loaded");
return false;
}
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp
index 189c3bc5531d..a41986de5143 100644
--- a/source/Core/Mangled.cpp
+++ b/source/Core/Mangled.cpp
@@ -10,7 +10,9 @@
// FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
#include <cstddef>
-#if defined(_MSC_VER) || defined (__FreeBSD__)
+#if defined(_MSC_VER)
+// Cannot enable the builtin demangler on msvc as it does not support the cpp11 within the implementation.
+#elif defined (__FreeBSD__)
#define LLDB_USE_BUILTIN_DEMANGLER
#else
#include <cxxabi.h>
@@ -4890,6 +4892,9 @@ Mangled::GetDemangledName () const
// add it to our map.
#ifdef LLDB_USE_BUILTIN_DEMANGLER
char *demangled_name = __cxa_demangle (mangled_cstr, NULL, NULL, NULL);
+#elif defined(_MSC_VER)
+ // Cannot demangle on msvc.
+ char *demangled_name = nullptr;
#else
char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
#endif
diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp
index 3f3be9360efa..f90a097416df 100644
--- a/source/Core/Module.cpp
+++ b/source/Core/Module.cpp
@@ -135,6 +135,7 @@ Module::Module (const ModuleSpec &module_spec) :
m_uuid (),
m_file (module_spec.GetFileSpec()),
m_platform_file(module_spec.GetPlatformFileSpec()),
+ m_remote_install_file(),
m_symfile_spec (module_spec.GetSymbolFileSpec()),
m_object_name (module_spec.GetObjectName()),
m_object_offset (module_spec.GetObjectOffset()),
@@ -179,6 +180,7 @@ Module::Module(const FileSpec& file_spec,
m_uuid (),
m_file (file_spec),
m_platform_file(),
+ m_remote_install_file (),
m_symfile_spec (),
m_object_name (),
m_object_offset (object_offset),
diff --git a/source/Core/StreamFile.cpp b/source/Core/StreamFile.cpp
index 9a4eb796dbea..2285ca954457 100644
--- a/source/Core/StreamFile.cpp
+++ b/source/Core/StreamFile.cpp
@@ -49,7 +49,7 @@ StreamFile::StreamFile (FILE *fh, bool transfer_ownership) :
StreamFile::StreamFile (const char *path) :
Stream (),
- m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate, File::ePermissionsDefault)
+ m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate, lldb::eFilePermissionsFileDefault)
{
}
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index 5767466f509d..a65b8f63e317 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -16,7 +16,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/ValueObject.h"
-#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
using namespace lldb_private;
diff --git a/source/DataFormatters/CXXFormatterFunctions.cpp b/source/DataFormatters/CXXFormatterFunctions.cpp
index e00413556cc9..136c8c51e660 100644
--- a/source/DataFormatters/CXXFormatterFunctions.cpp
+++ b/source/DataFormatters/CXXFormatterFunctions.cpp
@@ -49,9 +49,9 @@ lldb_private::formatters::ExtractValueFromObjCExpression (ValueObject &valobj,
return false;
EvaluateExpressionOptions options;
- options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(true);
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
target->EvaluateExpression(expr.GetData(),
stack_frame,
@@ -83,10 +83,10 @@ lldb_private::formatters::ExtractSummaryFromObjCExpression (ValueObject &valobj,
return false;
EvaluateExpressionOptions options;
- options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(true)
- .SetUseDynamic(lldb::eDynamicCanRunTarget);
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
+ options.SetUseDynamic(lldb::eDynamicCanRunTarget);
target->EvaluateExpression(expr.GetData(),
stack_frame,
@@ -121,10 +121,10 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
return valobj_sp;
EvaluateExpressionOptions options;
- options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(true)
- .SetUseDynamic(lldb::eDynamicCanRunTarget);
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
+ options.SetUseDynamic(lldb::eDynamicCanRunTarget);
target->EvaluateExpression(expr.GetData(),
stack_frame,
@@ -158,10 +158,10 @@ lldb_private::formatters::CallSelectorOnObject (ValueObject &valobj,
return valobj_sp;
EvaluateExpressionOptions options;
- options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(true)
- .SetUseDynamic(lldb::eDynamicCanRunTarget);
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetKeepInMemory(true);
+ options.SetUseDynamic(lldb::eDynamicCanRunTarget);
target->EvaluateExpression(expr.GetData(),
stack_frame,
diff --git a/source/DataFormatters/FormatClasses.cpp b/source/DataFormatters/FormatClasses.cpp
index c67f86a7493d..f27b45b30491 100644
--- a/source/DataFormatters/FormatClasses.cpp
+++ b/source/DataFormatters/FormatClasses.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/lldb-python.h"
+#include "lldb/DataFormatters/FormatClasses.h"
// C Includes
@@ -16,17 +16,6 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-public.h"
-#include "lldb/lldb-enumerations.h"
-
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/StreamString.h"
-#include "lldb/Core/Timer.h"
-#include "lldb/DataFormatters/FormatClasses.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Symbol/ClangASTType.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index b4c4628b48a2..bec2edf5d5c2 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -163,6 +163,139 @@ FormatManager::GetFormatAsCString (Format format)
return NULL;
}
+void
+FormatManager::GetPossibleMatches (ValueObject& valobj,
+ ClangASTType clang_type,
+ uint32_t reason,
+ lldb::DynamicValueType use_dynamic,
+ FormattersMatchVector& entries,
+ bool did_strip_ptr,
+ bool did_strip_ref,
+ bool did_strip_typedef,
+ bool root_level)
+{
+ clang_type = clang_type.RemoveFastQualifiers();
+ ConstString type_name(clang_type.GetConstTypeName());
+ if (valobj.GetBitfieldBitSize() > 0)
+ {
+ StreamString sstring;
+ sstring.Printf("%s:%d",type_name.AsCString(),valobj.GetBitfieldBitSize());
+ ConstString bitfieldname = ConstString(sstring.GetData());
+ entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef});
+ reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
+ }
+ entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
+
+ if (clang_type.IsReferenceType())
+ {
+ ClangASTType non_ref_type = clang_type.GetNonReferenceType();
+ GetPossibleMatches(valobj,
+ non_ref_type,
+ reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
+ use_dynamic,
+ entries,
+ did_strip_ptr,
+ true,
+ did_strip_typedef);
+ }
+ else if (clang_type.IsPointerType())
+ {
+ ClangASTType non_ptr_type = clang_type.GetPointeeType();
+ GetPossibleMatches(valobj,
+ non_ptr_type,
+ reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
+ use_dynamic,
+ entries,
+ true,
+ did_strip_ref,
+ did_strip_typedef);
+ }
+ bool canBeObjCDynamic = clang_type.IsPossibleDynamicType (NULL,
+ false, // no C
+ true); // yes ObjC
+
+ if (canBeObjCDynamic)
+ {
+ if (use_dynamic != lldb::eNoDynamicValues)
+ {
+ do
+ {
+ lldb::ProcessSP process_sp = valobj.GetProcessSP();
+ ObjCLanguageRuntime* runtime = process_sp->GetObjCLanguageRuntime();
+ if (runtime == nullptr)
+ break;
+ ObjCLanguageRuntime::ClassDescriptorSP objc_class_sp (runtime->GetClassDescriptor(valobj));
+ if (!objc_class_sp)
+ break;
+ ConstString name (objc_class_sp->GetClassName());
+ entries.push_back({name,reason | lldb_private::eFormatterChoiceCriterionDynamicObjCDiscovery,did_strip_ptr,did_strip_ref,did_strip_typedef});
+ } while (false);
+ }
+
+ ClangASTType non_ptr_type = clang_type.GetPointeeType();
+ GetPossibleMatches(valobj,
+ non_ptr_type,
+ reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
+ use_dynamic,
+ entries,
+ true,
+ did_strip_ref,
+ did_strip_typedef);
+ }
+
+ // try to strip typedef chains
+ if (clang_type.IsTypedefType())
+ {
+ ClangASTType deffed_type = clang_type.GetTypedefedType();
+ GetPossibleMatches(valobj,
+ deffed_type,
+ reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
+ use_dynamic,
+ entries,
+ did_strip_ptr,
+ did_strip_ref,
+ true);
+ }
+
+ if (root_level)
+ {
+ do {
+ if (!clang_type.IsValid())
+ break;
+
+ ClangASTType unqual_clang_ast_type = clang_type.GetFullyUnqualifiedType();
+ if (!unqual_clang_ast_type.IsValid())
+ break;
+ if (unqual_clang_ast_type.GetOpaqueQualType() != clang_type.GetOpaqueQualType())
+ GetPossibleMatches (valobj,
+ unqual_clang_ast_type,
+ reason,
+ use_dynamic,
+ entries,
+ did_strip_ptr,
+ did_strip_ref,
+ did_strip_typedef);
+ } while(false);
+
+
+ // if all else fails, go to static type
+ if (valobj.IsDynamic())
+ {
+ lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
+ if (static_value_sp)
+ GetPossibleMatches(*static_value_sp.get(),
+ static_value_sp->GetClangType(),
+ reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
+ use_dynamic,
+ entries,
+ did_strip_ptr,
+ did_strip_ref,
+ did_strip_typedef,
+ true);
+ }
+ }
+}
+
lldb::TypeFormatImplSP
FormatManager::GetFormatForType (lldb::TypeNameSpecifierImplSP type_sp)
{
diff --git a/source/DataFormatters/LibCxx.cpp b/source/DataFormatters/LibCxx.cpp
index cdc57f6bd937..21e104602a3f 100644
--- a/source/DataFormatters/LibCxx.cpp
+++ b/source/DataFormatters/LibCxx.cpp
@@ -35,10 +35,10 @@ m_options()
{
if (valobj_sp)
Update();
- m_options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(true)
- .SetUseDynamic(lldb::eDynamicCanRunTarget);
+ m_options.SetCoerceToId(false);
+ m_options.SetUnwindOnError(true);
+ m_options.SetKeepInMemory(true);
+ m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
}
size_t
diff --git a/source/DataFormatters/LibStdcpp.cpp b/source/DataFormatters/LibStdcpp.cpp
index e0f23cc35e3f..08e7d584003e 100644
--- a/source/DataFormatters/LibStdcpp.cpp
+++ b/source/DataFormatters/LibStdcpp.cpp
@@ -34,10 +34,10 @@ m_options()
{
if (valobj_sp)
Update();
- m_options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(true)
- .SetUseDynamic(lldb::eDynamicCanRunTarget);
+ m_options.SetCoerceToId(false);
+ m_options.SetUnwindOnError(true);
+ m_options.SetKeepInMemory(true);
+ m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
}
size_t
@@ -215,10 +215,10 @@ lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEnd::LibstdcppMapIte
{
if (valobj_sp)
Update();
- m_options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetKeepInMemory(true)
- .SetUseDynamic(lldb::eDynamicCanRunTarget);
+ m_options.SetCoerceToId(false);
+ m_options.SetUnwindOnError(true);
+ m_options.SetKeepInMemory(true);
+ m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
}
bool
diff --git a/source/DataFormatters/NSDictionary.cpp b/source/DataFormatters/NSDictionary.cpp
index 05a5dda39e53..f53004df5c5f 100644
--- a/source/DataFormatters/NSDictionary.cpp
+++ b/source/DataFormatters/NSDictionary.cpp
@@ -218,8 +218,10 @@ lldb_private::formatters::NSDictionaryCodeRunningSyntheticFrontEnd::GetChildAtIn
StreamString object_fetcher_expr;
object_fetcher_expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = %s; _lldb_valgen_item.value = %s; _lldb_valgen_item;",key_fetcher_expr.GetData(),value_fetcher_expr.GetData());
lldb::ValueObjectSP child_sp;
+ EvaluateExpressionOptions options;
+ options.SetKeepInMemory(true);
m_backend.GetTargetSP()->EvaluateExpression(object_fetcher_expr.GetData(), m_backend.GetFrameSP().get(), child_sp,
- EvaluateExpressionOptions().SetKeepInMemory(true));
+ options);
if (child_sp)
child_sp->SetName(ConstString(idx_name.GetData()));
return child_sp;
diff --git a/source/DataFormatters/NSSet.cpp b/source/DataFormatters/NSSet.cpp
index 02eb2bfc124f..e6fe2a34a67b 100644
--- a/source/DataFormatters/NSSet.cpp
+++ b/source/DataFormatters/NSSet.cpp
@@ -249,6 +249,10 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
if (idx >= num_children)
return lldb::ValueObjectSP();
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+
if (m_children.empty())
{
// do the scan phase
@@ -260,7 +264,6 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
while(tries < num_children)
{
obj_at_idx = m_data_ptr + (test_idx * m_ptr_size);
- ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
if (!process_sp)
return lldb::ValueObjectSP();
Error error;
@@ -286,12 +289,34 @@ lldb_private::formatters::NSSetISyntheticFrontEnd::GetChildAtIndex (size_t idx)
SetItemDescriptor &set_item = m_children[idx];
if (!set_item.valobj_sp)
{
- // make the new ValueObject
- StreamString expr;
- expr.Printf("(id)%" PRIu64,set_item.item_ptr);
+ auto ptr_size = process_sp->GetAddressByteSize();
+ DataBufferHeap buffer(ptr_size,0);
+ switch (ptr_size)
+ {
+ case 0: // architecture has no clue?? - fail
+ return lldb::ValueObjectSP();
+ case 4:
+ *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
+ break;
+ case 8:
+ *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
+ break;
+ default:
+ assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
+ }
StreamString idx_name;
idx_name.Printf("[%zu]",idx);
- set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
+
+ DataExtractor data(buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+
+ set_item.valobj_sp =
+ ValueObject::CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
}
return set_item.valobj_sp;
}
@@ -392,6 +417,10 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
if (idx >= num_children)
return lldb::ValueObjectSP();
+ ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
+ if (!process_sp)
+ return lldb::ValueObjectSP();
+
if (m_children.empty())
{
// do the scan phase
@@ -403,7 +432,6 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
while(tries < num_children)
{
obj_at_idx = m_objs_addr + (test_idx * m_ptr_size);
- ProcessSP process_sp = m_exe_ctx_ref.GetProcessSP();
if (!process_sp)
return lldb::ValueObjectSP();
Error error;
@@ -429,12 +457,34 @@ lldb_private::formatters::NSSetMSyntheticFrontEnd::GetChildAtIndex (size_t idx)
SetItemDescriptor &set_item = m_children[idx];
if (!set_item.valobj_sp)
{
- // make the new ValueObject
- StreamString expr;
- expr.Printf("(id)%" PRIu64,set_item.item_ptr);
+ auto ptr_size = process_sp->GetAddressByteSize();
+ DataBufferHeap buffer(ptr_size,0);
+ switch (ptr_size)
+ {
+ case 0: // architecture has no clue?? - fail
+ return lldb::ValueObjectSP();
+ case 4:
+ *((uint32_t*)buffer.GetBytes()) = (uint32_t)set_item.item_ptr;
+ break;
+ case 8:
+ *((uint64_t*)buffer.GetBytes()) = (uint64_t)set_item.item_ptr;
+ break;
+ default:
+ assert(false && "pointer size is not 4 nor 8 - get out of here ASAP");
+ }
StreamString idx_name;
idx_name.Printf("[%zu]",idx);
- set_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
+
+ DataExtractor data(buffer.GetBytes(),
+ buffer.GetByteSize(),
+ process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+
+ set_item.valobj_sp =
+ ValueObject::CreateValueObjectFromData(idx_name.GetData(),
+ data,
+ m_exe_ctx_ref,
+ m_backend.GetClangType().GetBasicTypeFromAST(lldb::eBasicTypeObjCID));
}
return set_item.valobj_sp;
}
diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp
index 636000bb23ea..a02560e78780 100644
--- a/source/DataFormatters/TypeCategory.cpp
+++ b/source/DataFormatters/TypeCategory.cpp
@@ -39,15 +39,15 @@ m_name(name)
bool
TypeCategoryImpl::Get (ValueObject& valobj,
+ const FormattersMatchVector& candidates,
lldb::TypeFormatImplSP& entry,
- lldb::DynamicValueType use_dynamic,
uint32_t* reason)
{
if (!IsEnabled())
return false;
- if (GetValueNavigator()->Get(valobj, entry, use_dynamic, reason))
+ if (GetValueNavigator()->Get(candidates, entry, reason))
return true;
- bool regex = GetRegexValueNavigator()->Get(valobj, entry, use_dynamic, reason);
+ bool regex = GetRegexValueNavigator()->Get(candidates, entry, reason);
if (regex && reason)
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
return regex;
@@ -55,25 +55,25 @@ TypeCategoryImpl::Get (ValueObject& valobj,
bool
TypeCategoryImpl::Get (ValueObject& valobj,
+ const FormattersMatchVector& candidates,
lldb::TypeSummaryImplSP& entry,
- lldb::DynamicValueType use_dynamic,
uint32_t* reason)
{
if (!IsEnabled())
return false;
- if (GetSummaryNavigator()->Get(valobj, entry, use_dynamic, reason))
+ if (GetSummaryNavigator()->Get(candidates, entry, reason))
return true;
- bool regex = GetRegexSummaryNavigator()->Get(valobj, entry, use_dynamic, reason);
+ bool regex = GetRegexSummaryNavigator()->Get(candidates, entry, reason);
if (regex && reason)
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary;
return regex;
}
bool
-TypeCategoryImpl::Get(ValueObject& valobj,
- lldb::SyntheticChildrenSP& entry_sp,
- lldb::DynamicValueType use_dynamic,
- uint32_t* reason)
+TypeCategoryImpl::Get (ValueObject& valobj,
+ const FormattersMatchVector& candidates,
+ lldb::SyntheticChildrenSP& entry,
+ uint32_t* reason)
{
if (!IsEnabled())
return false;
@@ -82,16 +82,16 @@ TypeCategoryImpl::Get(ValueObject& valobj,
bool regex_filter = false;
// first find both Filter and Synth, and then check which is most recent
- if (!GetFilterNavigator()->Get(valobj, filter_sp, use_dynamic, &reason_filter))
- regex_filter = GetRegexFilterNavigator()->Get (valobj, filter_sp, use_dynamic, &reason_filter);
+ if (!GetFilterNavigator()->Get(candidates, filter_sp, &reason_filter))
+ regex_filter = GetRegexFilterNavigator()->Get (candidates, filter_sp, &reason_filter);
#ifndef LLDB_DISABLE_PYTHON
bool regex_synth = false;
uint32_t reason_synth = 0;
bool pick_synth = false;
ScriptedSyntheticChildren::SharedPointer synth;
- if (!GetSyntheticNavigator()->Get(valobj, synth, use_dynamic, &reason_synth))
- regex_synth = GetRegexSyntheticNavigator()->Get (valobj, synth, use_dynamic, &reason_synth);
+ if (!GetSyntheticNavigator()->Get(candidates, synth, &reason_synth))
+ regex_synth = GetRegexSyntheticNavigator()->Get (candidates, synth, &reason_synth);
if (!filter_sp.get() && !synth.get())
return false;
else if (!filter_sp.get() && synth.get())
@@ -111,27 +111,26 @@ TypeCategoryImpl::Get(ValueObject& valobj,
{
if (regex_synth && reason)
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
- entry_sp = synth;
+ entry = synth;
return true;
}
else
{
if (regex_filter && reason)
*reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionFilter;
- entry_sp = filter_sp;
+ entry = filter_sp;
return true;
}
#else
if (filter_sp)
{
- entry_sp = filter_sp;
+ entry = filter_sp;
return true;
}
#endif
return false;
-
}
void
diff --git a/source/DataFormatters/TypeCategoryMap.cpp b/source/DataFormatters/TypeCategoryMap.cpp
index 621258806def..c6dba1b9f4bd 100644
--- a/source/DataFormatters/TypeCategoryMap.cpp
+++ b/source/DataFormatters/TypeCategoryMap.cpp
@@ -11,6 +11,9 @@
#include "lldb/DataFormatters/TypeCategoryMap.h"
+#include "lldb/DataFormatters/FormatClasses.h"
+#include "lldb/DataFormatters/FormatManager.h"
+
// C Includes
// C++ Includes
// Other libraries and framework includes
@@ -187,13 +190,15 @@ TypeCategoryMap::GetFormat (ValueObject& valobj,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeFormatImplSP current_format;
if (log)
log->Printf("\n[TypeCategoryMap::GetFormat] Trying to use category %s", category_sp->GetName());
- if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
+ if (!category_sp->Get(valobj, matches, current_format, &reason_why))
continue;
return current_format;
}
@@ -213,13 +218,15 @@ TypeCategoryMap::GetSummaryFormat (ValueObject& valobj,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeSummaryImplSP current_format;
if (log)
log->Printf("\n[CategoryMap::GetSummaryFormat] Trying to use category %s", category_sp->GetName());
- if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
+ if (!category_sp->Get(valobj, matches, current_format, &reason_why))
continue;
return current_format;
}
@@ -241,13 +248,15 @@ TypeCategoryMap::GetSyntheticChildren (ValueObject& valobj,
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ FormattersMatchVector matches = FormatManager::GetPossibleMatches(valobj, use_dynamic);
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::SyntheticChildrenSP current_format;
if (log)
log->Printf("\n[CategoryMap::GetSyntheticChildren] Trying to use category %s", category_sp->GetName());
- if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
+ if (!category_sp->Get(valobj, matches, current_format, &reason_why))
continue;
return current_format;
}
diff --git a/source/Expression/ClangFunction.cpp b/source/Expression/ClangFunction.cpp
index b37044df9ecc..e707c60ffced 100644
--- a/source/Expression/ClangFunction.cpp
+++ b/source/Expression/ClangFunction.cpp
@@ -394,14 +394,9 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add
ThreadPlan *
ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
- lldb::addr_t func_addr,
- lldb::addr_t &args_addr,
- Stream &errors,
- bool stop_others,
- bool unwind_on_error,
- bool ignore_breakpoints,
- lldb::addr_t *this_arg,
- lldb::addr_t *cmd_arg)
+ lldb::addr_t args_addr,
+ const EvaluateExpressionOptions &options,
+ Stream &errors)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
@@ -418,16 +413,15 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
// Okay, now run the function:
- Address wrapper_address (func_addr);
+ Address wrapper_address (m_jit_start_addr);
+
+ lldb::addr_t args = { args_addr };
+
ThreadPlan *new_plan = new ThreadPlanCallFunction (*thread,
wrapper_address,
ClangASTType(),
- args_addr,
- stop_others,
- unwind_on_error,
- ignore_breakpoints,
- this_arg,
- cmd_arg);
+ args,
+ options);
new_plan->SetIsMasterPlan(true);
new_plan->SetOkayToDiscard (false);
return new_plan;
@@ -479,63 +473,48 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_
}
ExecutionResults
-ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, Value &results)
-{
- return ExecuteFunction (exe_ctx, errors, 1000, true, results);
-}
-
-ExecutionResults
-ClangFunction::ExecuteFunction(ExecutionContext &exe_ctx, Stream &errors, bool stop_others, Value &results)
-{
- const bool try_all_threads = false;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
- return ExecuteFunction (exe_ctx, NULL, errors, stop_others, 0UL, try_all_threads,
- unwind_on_error, ignore_breakpoints, results);
-}
-
-ExecutionResults
ClangFunction::ExecuteFunction(
ExecutionContext &exe_ctx,
+ lldb::addr_t *args_addr_ptr,
+ const EvaluateExpressionOptions &options,
Stream &errors,
- uint32_t timeout_usec,
- bool try_all_threads,
Value &results)
{
- const bool stop_others = true;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
- return ExecuteFunction (exe_ctx, NULL, errors, stop_others, timeout_usec,
- try_all_threads, unwind_on_error, ignore_breakpoints, results);
-}
+ using namespace clang;
+ ExecutionResults return_value = eExecutionSetupError;
+
+ // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore
+ // breakpoints, unwind on error, and don't try to debug it.
+ EvaluateExpressionOptions real_options = options;
+ real_options.SetDebug(false);
+ real_options.SetUnwindOnError(true);
+ real_options.SetIgnoreBreakpoints(true);
+
+ lldb::addr_t args_addr;
+
+ if (args_addr_ptr != NULL)
+ args_addr = *args_addr_ptr;
+ else
+ args_addr = LLDB_INVALID_ADDRESS;
+
+ if (CompileFunction(errors) != 0)
+ return eExecutionSetupError;
+
+ if (args_addr == LLDB_INVALID_ADDRESS)
+ {
+ if (!InsertFunction(exe_ctx, args_addr, errors))
+ return eExecutionSetupError;
+ }
-// This is the static function
-ExecutionResults
-ClangFunction::ExecuteFunction (
- ExecutionContext &exe_ctx,
- lldb::addr_t function_address,
- lldb::addr_t &void_arg,
- bool stop_others,
- bool try_all_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- uint32_t timeout_usec,
- Stream &errors,
- lldb::addr_t *this_arg)
-{
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
log->Printf("== [ClangFunction::ExecuteFunction] Executing function ==");
- lldb::ThreadPlanSP call_plan_sp (ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
- function_address,
- void_arg,
- errors,
- stop_others,
- unwind_on_error,
- ignore_breakpoints,
- this_arg));
+ lldb::ThreadPlanSP call_plan_sp (GetThreadPlanToCallFunction (exe_ctx,
+ args_addr,
+ real_options,
+ errors));
if (!call_plan_sp)
return eExecutionSetupError;
@@ -544,17 +523,14 @@ ClangFunction::ExecuteFunction (
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
- ExecutionResults results = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, call_plan_sp,
- stop_others,
- try_all_threads,
- unwind_on_error,
- ignore_breakpoints,
- timeout_usec,
- errors);
+ return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
+ call_plan_sp,
+ real_options,
+ errors);
if (log)
{
- if (results != eExecutionCompleted)
+ if (return_value != eExecutionCompleted)
{
log->Printf("== [ClangFunction::ExecuteFunction] Execution completed abnormally ==");
}
@@ -567,50 +543,6 @@ ClangFunction::ExecuteFunction (
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
- return results;
-}
-
-ExecutionResults
-ClangFunction::ExecuteFunction(
- ExecutionContext &exe_ctx,
- lldb::addr_t *args_addr_ptr,
- Stream &errors,
- bool stop_others,
- uint32_t timeout_usec,
- bool try_all_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- Value &results)
-{
- using namespace clang;
- ExecutionResults return_value = eExecutionSetupError;
-
- lldb::addr_t args_addr;
-
- if (args_addr_ptr != NULL)
- args_addr = *args_addr_ptr;
- else
- args_addr = LLDB_INVALID_ADDRESS;
-
- if (CompileFunction(errors) != 0)
- return eExecutionSetupError;
-
- if (args_addr == LLDB_INVALID_ADDRESS)
- {
- if (!InsertFunction(exe_ctx, args_addr, errors))
- return eExecutionSetupError;
- }
-
- return_value = ClangFunction::ExecuteFunction (exe_ctx,
- m_jit_start_addr,
- args_addr,
- stop_others,
- try_all_threads,
- unwind_on_error,
- ignore_breakpoints,
- timeout_usec,
- errors);
-
if (args_addr_ptr != NULL)
*args_addr_ptr = args_addr;
diff --git a/source/Expression/ClangUserExpression.cpp b/source/Expression/ClangUserExpression.cpp
index e4f2830ba259..d9ecd41be97a 100644
--- a/source/Expression/ClangUserExpression.cpp
+++ b/source/Expression/ClangUserExpression.cpp
@@ -716,35 +716,6 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
return true;
}
-ThreadPlan *
-ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx)
-{
- lldb::addr_t struct_address;
-
- lldb::addr_t object_ptr = 0;
- lldb::addr_t cmd_ptr = 0;
-
- PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr);
-
- // FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
- // ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
- // forcing unwind_on_error to be true here, in practical terms that can't happen.
-
- const bool stop_others = true;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = false;
- return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
- m_jit_start_addr,
- struct_address,
- error_stream,
- stop_others,
- unwind_on_error,
- ignore_breakpoints,
- (m_needs_object_ptr ? &object_ptr : NULL),
- (m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
-}
-
bool
ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
ExecutionContext &exe_ctx,
@@ -852,27 +823,22 @@ ClangUserExpression::Execute (Stream &error_stream,
}
else
{
- const uint32_t timeout_usec = options.GetTimeoutUsec();
- const bool debug = options.GetDebug();
- const bool unwind_on_error = debug ? false : options.DoesUnwindOnError();
- const bool ignore_breakpoints = debug ? false : options.DoesIgnoreBreakpoints();
- const bool stop_others = true;
- const bool try_all_threads = options.GetRunOthers();
- lldb::BreakpointSP debug_bkpt_sp;
- if (debug)
- {
- // TODO: push this down into the thread plan and let the plan manage it
- debug_bkpt_sp = exe_ctx.GetTargetRef().CreateBreakpoint(m_jit_start_addr, false, false);
- }
Address wrapper_address (m_jit_start_addr);
+
+ llvm::SmallVector <lldb::addr_t, 3> args;
+
+ if (m_needs_object_ptr) {
+ args.push_back(object_ptr);
+ if (m_objectivec)
+ args.push_back(cmd_ptr);
+ }
+
+ args.push_back(struct_address);
+
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
wrapper_address,
- struct_address,
- stop_others,
- unwind_on_error,
- ignore_breakpoints,
- (m_needs_object_ptr ? &object_ptr : NULL),
- ((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
+ args,
+ options,
shared_ptr_to_me));
if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
@@ -890,19 +856,10 @@ ClangUserExpression::Execute (Stream &error_stream,
exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
ExecutionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
- call_plan_sp,
- stop_others,
- try_all_threads,
- unwind_on_error,
- ignore_breakpoints,
- timeout_usec,
+ call_plan_sp,
+ options,
error_stream);
- if (debug_bkpt_sp)
- {
- exe_ctx.GetTargetRef().RemoveBreakpointByID(debug_bkpt_sp->GetID());
- }
-
if (exe_ctx.GetProcessPtr())
exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
@@ -922,16 +879,22 @@ ClangUserExpression::Execute (Stream &error_stream,
if (error_desc)
error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
else
- error_stream.Printf ("Execution was interrupted.");
+ error_stream.PutCString ("Execution was interrupted.");
- if ((execution_result == eExecutionInterrupted && unwind_on_error)
- || (execution_result == eExecutionHitBreakpoint && ignore_breakpoints))
- error_stream.Printf ("\nThe process has been returned to the state before expression evaluation.");
+ if ((execution_result == eExecutionInterrupted && options.DoesUnwindOnError())
+ || (execution_result == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints()))
+ error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
else
- error_stream.Printf ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
+ error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, use \"thread return -x\" to return to the state before expression evaluation.");
return execution_result;
}
+ else if (execution_result == eExecutionStoppedForDebug)
+ {
+ error_stream.PutCString ("Execution was halted at the first instruction of the expression function because \"debug\" was requested.\n"
+ "Use \"thread return -x\" to return to the state before expression evaluation.");
+ return execution_result;
+ }
else if (execution_result != eExecutionCompleted)
{
error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp
index fb9522f0dc36..8731fbebd148 100644
--- a/source/Expression/Materializer.cpp
+++ b/source/Expression/Materializer.cpp
@@ -492,7 +492,10 @@ public:
}
else
{
- err.SetErrorStringWithFormat("size of variable %s disagrees with the ValueObject's size", m_variable_sp->GetName().AsCString());
+ err.SetErrorStringWithFormat("size of variable %s (%" PRIu64 ") disagrees with the ValueObject's size (%" PRIu64 ")",
+ m_variable_sp->GetName().AsCString(),
+ m_variable_sp->GetType()->GetByteSize(),
+ data.GetByteSize());
}
return;
}
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index addd43515405..bbd11858aaba 100644
--- a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -1,4 +1,4 @@
-//===-- FileSpec.cpp --------------------------------------------*- C++ -*-===//
+//===-- File.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "lldb/Host/File.h"
#include <errno.h>
@@ -237,6 +236,11 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
else if (read)
{
oflag |= O_RDONLY;
+
+#ifndef _WIN32
+ if (options & eOpenoptionDontFollowSymlinks)
+ oflag |= O_NOFOLLOW;
+#endif
}
#ifndef _WIN32
@@ -249,15 +253,15 @@ File::Open (const char *path, uint32_t options, uint32_t permissions)
mode_t mode = 0;
if (oflag & O_CREAT)
{
- if (permissions & ePermissionsUserRead) mode |= S_IRUSR;
- if (permissions & ePermissionsUserWrite) mode |= S_IWUSR;
- if (permissions & ePermissionsUserExecute) mode |= S_IXUSR;
- if (permissions & ePermissionsGroupRead) mode |= S_IRGRP;
- if (permissions & ePermissionsGroupWrite) mode |= S_IWGRP;
- if (permissions & ePermissionsGroupExecute) mode |= S_IXGRP;
- if (permissions & ePermissionsWorldRead) mode |= S_IROTH;
- if (permissions & ePermissionsWorldWrite) mode |= S_IWOTH;
- if (permissions & ePermissionsWorldExecute) mode |= S_IXOTH;
+ if (permissions & lldb::eFilePermissionsUserRead) mode |= S_IRUSR;
+ if (permissions & lldb::eFilePermissionsUserWrite) mode |= S_IWUSR;
+ if (permissions & lldb::eFilePermissionsUserExecute) mode |= S_IXUSR;
+ if (permissions & lldb::eFilePermissionsGroupRead) mode |= S_IRGRP;
+ if (permissions & lldb::eFilePermissionsGroupWrite) mode |= S_IWGRP;
+ if (permissions & lldb::eFilePermissionsGroupExecute) mode |= S_IXGRP;
+ if (permissions & lldb::eFilePermissionsWorldRead) mode |= S_IROTH;
+ if (permissions & lldb::eFilePermissionsWorldWrite) mode |= S_IWOTH;
+ if (permissions & lldb::eFilePermissionsWorldExecute) mode |= S_IXOTH;
}
do
@@ -284,7 +288,7 @@ File::GetPermissions (const char *path, Error &error)
else
{
error.Clear();
- return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
}
}
else
@@ -309,7 +313,7 @@ File::GetPermissions(Error &error) const
else
{
error.Clear();
- return file_stats.st_mode; // All bits from lldb_private::File::Permissions match those in POSIX mode bits
+ return file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
}
}
else
diff --git a/source/Host/common/FileSpec.cpp b/source/Host/common/FileSpec.cpp
index 33de198072dc..48f1ac78d927 100644
--- a/source/Host/common/FileSpec.cpp
+++ b/source/Host/common/FileSpec.cpp
@@ -34,6 +34,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataBufferMemoryMap.h"
#include "lldb/Core/RegularExpression.h"
@@ -646,6 +647,15 @@ FileSpec::GetFileType () const
return eFileTypeInvalid;
}
+uint32_t
+FileSpec::GetPermissions () const
+{
+ uint32_t file_permissions = 0;
+ if (*this)
+ Host::GetFilePermissions(GetPath().c_str(), file_permissions);
+ return file_permissions;
+}
+
TimeValue
FileSpec::GetModificationTime () const
{
@@ -1161,26 +1171,26 @@ FileSpec::CopyByRemovingLastPathComponent () const
return FileSpec(m_directory.GetCString(),resolve);
}
-const char*
+ConstString
FileSpec::GetLastPathComponent () const
{
- if (m_filename.IsEmpty() && m_directory.IsEmpty())
- return NULL;
- if (m_filename.IsEmpty())
+ if (m_filename)
+ return m_filename;
+ if (m_directory)
{
const char* dir_cstr = m_directory.GetCString();
const char* last_slash_ptr = ::strrchr(dir_cstr, '/');
if (last_slash_ptr == NULL)
- return m_directory.GetCString();
+ return m_directory;
if (last_slash_ptr == dir_cstr)
{
if (last_slash_ptr[1] == 0)
- return last_slash_ptr;
+ return ConstString(last_slash_ptr);
else
- return last_slash_ptr+1;
+ return ConstString(last_slash_ptr+1);
}
if (last_slash_ptr[1] != 0)
- return last_slash_ptr+1;
+ return ConstString(last_slash_ptr+1);
const char* penultimate_slash_ptr = last_slash_ptr;
while (*penultimate_slash_ptr)
{
@@ -1190,10 +1200,10 @@ FileSpec::GetLastPathComponent () const
if (*penultimate_slash_ptr == '/')
break;
}
- ConstString new_path(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
- return new_path.AsCString();
+ ConstString result(penultimate_slash_ptr+1,last_slash_ptr-penultimate_slash_ptr);
+ return result;
}
- return m_filename.GetCString();
+ return ConstString();
}
void
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index 296e4b40bf01..262776f6c719 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -22,6 +22,7 @@
#include <grp.h>
#include <netdb.h>
#include <pwd.h>
+#include <sys/stat.h>
#endif
#if !defined (__GNU__) && !defined (_WIN32)
@@ -33,6 +34,7 @@
#include <mach/mach_port.h>
#include <mach/mach_init.h>
#include <mach-o/dyld.h>
+#include <AvailabilityMacros.h>
#endif
#if defined (__linux__) || defined (__FreeBSD__) || defined (__FreeBSD_kernel__)
@@ -978,6 +980,7 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
// on linux this is assumed to be the "lldb" main executable. If LLDB on
// linux is actually in a shared library (liblldb.so) then this function will
// need to be modified to "do the right thing".
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST);
switch (path_type)
{
@@ -988,6 +991,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
{
FileSpec lldb_file_spec (Host::GetModuleFileSpecForHostAddress ((void *)Host::GetLLDBPath));
g_lldb_so_dir = lldb_file_spec.GetDirectory();
+ if (log)
+ log->Printf("Host::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_lldb_so_dir.GetCString());
}
file_spec.GetDirectory() = g_lldb_so_dir;
return (bool)file_spec.GetDirectory();
@@ -1011,7 +1016,11 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
if (framework_pos)
{
framework_pos += strlen("LLDB.framework");
-#if !defined (__arm__)
+#if defined (__arm__)
+ // Shallow bundle
+ *framework_pos = '\0';
+#else
+ // Normal bundle
::strncpy (framework_pos, "/Resources", PATH_MAX - (framework_pos - raw_path));
#endif
}
@@ -1019,6 +1028,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
g_lldb_support_exe_dir.SetCString(resolved_path);
}
+ if (log)
+ log->Printf("Host::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'", g_lldb_support_exe_dir.GetCString());
}
file_spec.GetDirectory() = g_lldb_support_exe_dir;
return (bool)file_spec.GetDirectory();
@@ -1051,6 +1062,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
// TODO: Anyone know how we can determine this for linux? Other systems??
g_lldb_headers_dir.SetCString ("/opt/local/include/lldb");
#endif
+ if (log)
+ log->Printf("Host::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_lldb_headers_dir.GetCString());
}
file_spec.GetDirectory() = g_lldb_headers_dir;
return (bool)file_spec.GetDirectory();
@@ -1096,6 +1109,10 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
FileSpec::Resolve (raw_path, resolved_path, sizeof(resolved_path));
g_lldb_python_dir.SetCString(resolved_path);
}
+
+ if (log)
+ log->Printf("Host::GetLLDBPath(ePathTypePythonDir) => '%s'", g_lldb_python_dir.GetCString());
+
}
file_spec.GetDirectory() = g_lldb_python_dir;
return (bool)file_spec.GetDirectory();
@@ -1136,6 +1153,10 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
g_lldb_system_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
}
#endif // __APPLE__ || __linux__
+
+ if (log)
+ log->Printf("Host::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'", g_lldb_system_plugin_dir.GetCString());
+
}
if (g_lldb_system_plugin_dir)
@@ -1194,6 +1215,8 @@ Host::GetLLDBPath (PathType path_type, FileSpec &file_spec)
if (lldb_file_spec.Exists())
g_lldb_user_plugin_dir.SetCString(lldb_file_spec.GetPath().c_str());
+ if (log)
+ log->Printf("Host::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'", g_lldb_user_plugin_dir.GetCString());
}
file_spec.GetDirectory() = g_lldb_user_plugin_dir;
return (bool)file_spec.GetDirectory();
@@ -1546,7 +1569,7 @@ Host::RunShellCommand (const char *command,
return error;
}
-#if defined(__linux__) or defined(__FreeBSD__)
+#if defined(__linux__) || defined(__FreeBSD__)
// The functions below implement process launching via posix_spawn() for Linux
// and FreeBSD.
@@ -1826,11 +1849,168 @@ Host::LaunchApplication (const FileSpec &app_file_spec)
return LLDB_INVALID_PROCESS_ID;
}
-uint32_t
-Host::MakeDirectory (const char* path, mode_t mode)
+#endif
+
+
+#ifdef LLDB_DISABLE_POSIX
+
+Error
+Host::MakeDirectory (const char* path, uint32_t mode)
+{
+ Error error;
+ error.SetErrorStringWithFormat("%s in not implemented on this host", __PRETTY_FUNCTION__);
+ return error;
+}
+
+Error
+Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
{
- return UINT32_MAX;
+ Error error;
+ error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
+ return error;
}
+
+Error
+Host::SetFilePermissions (const char* path, uint32_t file_permissions)
+{
+ Error error;
+ error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
+ return error;
+}
+
+Error
+Host::Symlink (const char *src, const char *dst)
+{
+ Error error;
+ error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
+ return error;
+}
+
+Error
+Host::Readlink (const char *path, char *buf, size_t buf_len)
+{
+ Error error;
+ error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
+ return error;
+}
+
+Error
+Host::Unlink (const char *path)
+{
+ Error error;
+ error.SetErrorStringWithFormat("%s is not supported on this host", __PRETTY_FUNCTION__);
+ return error;
+}
+
+#else
+
+Error
+Host::MakeDirectory (const char* path, uint32_t file_permissions)
+{
+ Error error;
+ if (path && path[0])
+ {
+ if (::mkdir(path, file_permissions) != 0)
+ {
+ error.SetErrorToErrno();
+ switch (error.GetError())
+ {
+ case ENOENT:
+ {
+ // Parent directory doesn't exist, so lets make it if we can
+ FileSpec spec(path, false);
+ if (spec.GetDirectory() && spec.GetFilename())
+ {
+ // Make the parent directory and try again
+ Error error2 = Host::MakeDirectory(spec.GetDirectory().GetCString(), file_permissions);
+ if (error2.Success())
+ {
+ // Try and make the directory again now that the parent directory was made successfully
+ if (::mkdir(path, file_permissions) == 0)
+ error.Clear();
+ else
+ error.SetErrorToErrno();
+ }
+ }
+ }
+ break;
+ case EEXIST:
+ {
+ FileSpec path_spec(path, false);
+ if (path_spec.IsDirectory())
+ error.Clear(); // It is a directory and it already exists
+ }
+ break;
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("empty path");
+ }
+ return error;
+}
+
+Error
+Host::GetFilePermissions (const char* path, uint32_t &file_permissions)
+{
+ Error error;
+ struct stat file_stats;
+ if (::stat (path, &file_stats) == 0)
+ {
+ // The bits in "st_mode" currently match the definitions
+ // for the file mode bits in unix.
+ file_permissions = file_stats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ else
+ {
+ error.SetErrorToErrno();
+ }
+ return error;
+}
+
+Error
+Host::SetFilePermissions (const char* path, uint32_t file_permissions)
+{
+ Error error;
+ if (::chmod(path, file_permissions) != 0)
+ error.SetErrorToErrno();
+ return error;
+}
+
+Error
+Host::Symlink (const char *src, const char *dst)
+{
+ Error error;
+ if (::symlink(dst, src) == -1)
+ error.SetErrorToErrno();
+ return error;
+}
+
+Error
+Host::Unlink (const char *path)
+{
+ Error error;
+ if (::unlink(path) == -1)
+ error.SetErrorToErrno();
+ return error;
+}
+
+Error
+Host::Readlink (const char *path, char *buf, size_t buf_len)
+{
+ Error error;
+ ssize_t count = ::readlink(path, buf, buf_len);
+ if (count < 0)
+ error.SetErrorToErrno();
+ else if (count < (buf_len-1))
+ buf[count] = '\0'; // Success
+ else
+ error.SetErrorString("'buf' buffer is too small to contain link contents");
+ return error;
+}
+
+
#endif
typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap;
@@ -1843,7 +2023,7 @@ FDToFileMap& GetFDToFileMap()
lldb::user_id_t
Host::OpenFile (const FileSpec& file_spec,
uint32_t flags,
- mode_t mode,
+ uint32_t mode,
Error &error)
{
std::string path (file_spec.GetPath());
diff --git a/source/Host/common/OptionParser.cpp b/source/Host/common/OptionParser.cpp
index 287292ee74af..ead044f53cf1 100644
--- a/source/Host/common/OptionParser.cpp
+++ b/source/Host/common/OptionParser.cpp
@@ -38,24 +38,70 @@ OptionParser::EnableError(bool error)
}
int
-OptionParser::Parse(int argc, char * const argv [],
- const char *optstring,
- const Option *longopts, int *longindex)
+OptionParser::Parse (int argc,
+ char * const argv [],
+ const char *optstring,
+ const Option *longopts,
+ int *longindex)
{
return getopt_long_only(argc, argv, optstring, (const option*)longopts, longindex);
}
-char* OptionParser::GetOptionArgument()
+char*
+OptionParser::GetOptionArgument()
{
return optarg;
}
-int OptionParser::GetOptionIndex()
+int
+OptionParser::GetOptionIndex()
{
return optind;
}
-int OptionParser::GetOptionErrorCause()
+int
+OptionParser::GetOptionErrorCause()
{
return optopt;
}
+
+std::string
+OptionParser::GetShortOptionString(struct option *long_options)
+{
+ std::string s;
+ int i=0;
+ bool done = false;
+ while (!done)
+ {
+ if (long_options[i].name == 0 &&
+ long_options[i].has_arg == 0 &&
+ long_options[i].flag == 0 &&
+ long_options[i].val == 0)
+ {
+ done = true;
+ }
+ else
+ {
+ if (long_options[i].flag == NULL &&
+ isalpha(long_options[i].val))
+ {
+ s.append(1, (char)long_options[i].val);
+ switch (long_options[i].has_arg)
+ {
+ default:
+ case no_argument:
+ break;
+
+ case optional_argument:
+ s.append(2, ':');
+ break;
+ case required_argument:
+ s.append(1, ':');
+ break;
+ }
+ }
+ ++i;
+ }
+ }
+ return s;
+}
diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp
index 7189269677d9..41f465abc836 100644
--- a/source/Host/common/Symbols.cpp
+++ b/source/Host/common/Symbols.cpp
@@ -61,9 +61,9 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
uuid_str = uuid_str + ".debug";
}
- // Get full path to our module. Needed to check debug files like this:
- // /usr/lib/debug/usr/lib/libboost_date_time.so.1.46.1
- std::string module_filename = module_spec.GetFileSpec().GetPath();
+ // Get directory of our module. Needed to check debug files like this:
+ // /usr/lib/debug/usr/lib/library.so.debug
+ std::string module_directory = module_spec.GetFileSpec().GetDirectory().AsCString();
size_t num_directories = debug_file_search_paths.GetSize();
for (size_t idx = 0; idx < num_directories; ++idx)
@@ -79,7 +79,7 @@ Symbols::LocateExecutableSymbolFile (const ModuleSpec &module_spec)
files.push_back (dirname + "/" + symbol_filename);
files.push_back (dirname + "/.debug/" + symbol_filename);
files.push_back (dirname + "/.build-id/" + uuid_str);
- files.push_back (dirname + module_filename);
+ files.push_back (dirname + module_directory + "/" + symbol_filename);
const uint32_t num_files = files.size();
for (size_t idx_file = 0; idx_file < num_files; ++idx_file)
diff --git a/source/Interpreter/Args.cpp b/source/Interpreter/Args.cpp
index ff94e0f60212..b6f34fd1f7fb 100644
--- a/source/Interpreter/Args.cpp
+++ b/source/Interpreter/Args.cpp
@@ -815,7 +815,7 @@ Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::add
options.SetCoerceToId(false);
options.SetUnwindOnError(true);
options.SetKeepInMemory(false);
- options.SetRunOthers(true);
+ options.SetTryAllThreads(true);
ExecutionResults expr_result = target->EvaluateExpression(s,
exe_ctx->GetFramePtr(),
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index 794cc716bda5..a7c892d255e8 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -1434,12 +1434,12 @@ CommandInterpreter::PreprocessCommand (std::string &command)
ValueObjectSP expr_result_valobj_sp;
EvaluateExpressionOptions options;
- options.SetCoerceToId(false)
- .SetUnwindOnError(true)
- .SetIgnoreBreakpoints(true)
- .SetKeepInMemory(false)
- .SetRunOthers(true)
- .SetTimeoutUsec(0);
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetKeepInMemory(false);
+ options.SetTryAllThreads(true);
+ options.SetTimeoutUsec(0);
ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
exe_ctx.GetFramePtr(),
@@ -1498,6 +1498,9 @@ CommandInterpreter::PreprocessCommand (std::string &command)
case eExecutionTimedOut:
error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str());
break;
+ case eExecutionStoppedForDebug:
+ error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str());
+ break;
}
}
}
diff --git a/source/Interpreter/PythonDataObjects.cpp b/source/Interpreter/PythonDataObjects.cpp
index da4e085e2398..1e2bd2391191 100644
--- a/source/Interpreter/PythonDataObjects.cpp
+++ b/source/Interpreter/PythonDataObjects.cpp
@@ -15,11 +15,7 @@
#else
-#if defined (__APPLE__)
-#include <Python/Python.h>
-#else
-#include <Python.h>
-#endif
+#include "lldb/lldb-python.h"
#include <stdio.h>
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index fc76f0470d3a..fb60fedbe94b 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -15,12 +15,7 @@
#else
-#if defined (__APPLE__)
-#include <Python/Python.h>
-#else
-#include <Python.h>
-#endif
-
+#include "lldb/lldb-python.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include <stdlib.h>
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index f27c294a4abd..abf873ff3dd1 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -198,12 +198,7 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
addr_t sp,
addr_t function_addr,
addr_t return_addr,
- addr_t *arg1_ptr,
- addr_t *arg2_ptr,
- addr_t *arg3_ptr,
- addr_t *arg4_ptr,
- addr_t *arg5_ptr,
- addr_t *arg6_ptr) const
+ llvm::ArrayRef<addr_t> args) const
{
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -215,50 +210,45 @@ ABIMacOSX_arm::PrepareTrivialCall (Thread &thread,
RegisterValue reg_value;
- if (arg1_ptr)
+ const char *reg_names[] = { "r0", "r1", "r2", "r3" };
+
+ llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
+
+ for (size_t i = 0; i < (sizeof(reg_names) / sizeof(reg_names[0])); ++i)
{
- reg_value.SetUInt32(*arg1_ptr);
- if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r0"), reg_value))
+ if (ai == ae)
+ break;
+
+ reg_value.SetUInt32(*ai);
+ if (!reg_ctx->WriteRegister(reg_ctx->GetRegisterInfoByName(reg_names[i]), reg_value))
return false;
-
- if (arg2_ptr)
+
+ ++ai;
+ }
+
+ if (ai != ae)
+ {
+ // Spill onto the stack
+ size_t num_stack_regs = ae - ai;
+
+ sp -= (num_stack_regs * 4);
+ // Keep the stack 8 byte aligned, not that we need to
+ sp &= ~(8ull-1ull);
+
+ // just using arg1 to get the right size
+ const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+
+ addr_t arg_pos = sp;
+
+ for (; ai != ae; ++ai)
{
- reg_value.SetUInt32(*arg2_ptr);
- if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r1"), reg_value))
+ reg_value.SetUInt32(*ai);
+ if (reg_ctx->WriteRegisterValueToMemory(reg_info, arg_pos, reg_info->byte_size, reg_value).Fail())
return false;
-
- if (arg3_ptr)
- {
- reg_value.SetUInt32(*arg3_ptr);
- if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r2"), reg_value))
- return false;
- if (arg4_ptr)
- {
- reg_value.SetUInt32(*arg4_ptr);
- const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3");
- if (!reg_ctx->WriteRegister (reg_info, reg_value))
- return false;
- if (arg5_ptr)
- {
- // Keep the stack 8 byte aligned, not that we need to
- sp -= 8;
- sp &= ~(8ull-1ull);
- reg_value.SetUInt32(*arg5_ptr);
- if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp, reg_info->byte_size, reg_value).Fail())
- return false;
- if (arg6_ptr)
- {
- reg_value.SetUInt32(*arg6_ptr);
- if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp + 4, reg_info->byte_size, reg_value).Fail())
- return false;
- }
- }
- }
- }
+ arg_pos += reg_info->byte_size;
}
}
-
TargetSP target_sp (thread.CalculateTarget());
Address so_addr;
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
index 27cea85aaf6f..6f7b339e28a2 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
@@ -30,12 +30,7 @@ public:
lldb::addr_t sp,
lldb::addr_t func_addr,
lldb::addr_t returnAddress,
- lldb::addr_t *arg1_ptr = NULL,
- lldb::addr_t *arg2_ptr = NULL,
- lldb::addr_t *arg3_ptr = NULL,
- lldb::addr_t *arg4_ptr = NULL,
- lldb::addr_t *arg5_ptr = NULL,
- lldb::addr_t *arg6_ptr = NULL) const;
+ llvm::ArrayRef<lldb::addr_t> args) const;
virtual bool
GetArgumentValues (lldb_private::Thread &thread,
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index ecf44b9c4f73..f360a182e065 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -260,12 +260,7 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
addr_t sp,
addr_t func_addr,
addr_t return_addr,
- addr_t *arg1_ptr,
- addr_t *arg2_ptr,
- addr_t *arg3_ptr,
- addr_t *arg4_ptr,
- addr_t *arg5_ptr,
- addr_t *arg6_ptr) const
+ llvm::ArrayRef<addr_t> args) const
{
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
@@ -287,114 +282,25 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
RegisterValue reg_value;
// Write any arguments onto the stack
- if (arg1_ptr)
- {
- sp -= 4;
- if (arg2_ptr)
- {
- sp -= 4;
- if (arg3_ptr)
- {
- sp -= 4;
- if (arg4_ptr)
- {
- sp -= 4;
- if (arg5_ptr)
- {
- sp -= 4;
- if (arg6_ptr)
- {
- sp -= 4;
- }
- }
- }
- }
- }
- }
-
+ sp -= 4 * args.size();
+
// Align the SP
sp &= ~(16ull-1ull); // 16-byte alignment
- if (arg1_ptr)
+ addr_t arg_pos = sp;
+
+ for (addr_t arg : args)
{
- reg_value.SetUInt32(*arg1_ptr);
- error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
- sp,
- reg_info_32->byte_size,
+ reg_value.SetUInt32(arg);
+ error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
+ arg_pos,
+ reg_info_32->byte_size,
reg_value);
if (error.Fail())
return false;
-
- if (arg2_ptr)
- {
- reg_value.SetUInt32(*arg2_ptr);
- // The register info used to write memory just needs to have the correct
- // size of a 32 bit register, the actual register it pertains to is not
- // important, just the size needs to be correct. Here we use "eax"...
- error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
- sp + 4,
- reg_info_32->byte_size,
- reg_value);
- if (error.Fail())
- return false;
-
- if (arg3_ptr)
- {
- reg_value.SetUInt32(*arg3_ptr);
- // The register info used to write memory just needs to have the correct
- // size of a 32 bit register, the actual register it pertains to is not
- // important, just the size needs to be correct. Here we use "eax"...
- error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
- sp + 8,
- reg_info_32->byte_size,
- reg_value);
- if (error.Fail())
- return false;
-
- if (arg4_ptr)
- {
- reg_value.SetUInt32(*arg4_ptr);
- // The register info used to write memory just needs to have the correct
- // size of a 32 bit register, the actual register it pertains to is not
- // important, just the size needs to be correct. Here we use "eax"...
- error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
- sp + 12,
- reg_info_32->byte_size,
- reg_value);
- if (error.Fail())
- return false;
- if (arg5_ptr)
- {
- reg_value.SetUInt32(*arg5_ptr);
- // The register info used to write memory just needs to have the correct
- // size of a 32 bit register, the actual register it pertains to is not
- // important, just the size needs to be correct. Here we use "eax"...
- error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
- sp + 16,
- reg_info_32->byte_size,
- reg_value);
- if (error.Fail())
- return false;
- if (arg6_ptr)
- {
- reg_value.SetUInt32(*arg6_ptr);
- // The register info used to write memory just needs to have the correct
- // size of a 32 bit register, the actual register it pertains to is not
- // important, just the size needs to be correct. Here we use "eax"...
- error = reg_ctx->WriteRegisterValueToMemory (reg_info_32,
- sp + 20,
- reg_info_32->byte_size,
- reg_value);
- if (error.Fail())
- return false;
- }
- }
- }
- }
- }
+ arg_pos += 4;
}
-
// The return address is pushed onto the stack (yes after we just set the
// alignment above!).
sp -= 4;
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index 5428d0c1e44e..a2eee280fa38 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -33,12 +33,7 @@ public:
lldb::addr_t sp,
lldb::addr_t func_addr,
lldb::addr_t return_addr,
- lldb::addr_t *arg1_ptr = NULL,
- lldb::addr_t *arg2_ptr = NULL,
- lldb::addr_t *arg3_ptr = NULL,
- lldb::addr_t *arg4_ptr = NULL,
- lldb::addr_t *arg5_ptr = NULL,
- lldb::addr_t *arg6_ptr = NULL) const;
+ llvm::ArrayRef<lldb::addr_t> args) const;
virtual bool
PrepareNormalCall (lldb_private::Thread &thread,
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
index a8cf714a13b3..a8ef6a51399c 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -303,12 +303,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
addr_t sp,
addr_t func_addr,
addr_t return_addr,
- addr_t *arg1_ptr,
- addr_t *arg2_ptr,
- addr_t *arg3_ptr,
- addr_t *arg4_ptr,
- addr_t *arg5_ptr,
- addr_t *arg6_ptr) const
+ llvm::ArrayRef<addr_t> args) const
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
@@ -321,28 +316,8 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
(uint64_t)func_addr,
(uint64_t)return_addr);
- if (arg1_ptr)
- {
- s.Printf (", arg1 = 0x%" PRIx64, (uint64_t)*arg1_ptr);
- if (arg2_ptr)
- {
- s.Printf (", arg2 = 0x%" PRIx64, (uint64_t)*arg2_ptr);
- if (arg3_ptr)
- {
- s.Printf (", arg3 = 0x%" PRIx64, (uint64_t)*arg3_ptr);
- if (arg4_ptr)
- {
- s.Printf (", arg4 = 0x%" PRIx64, (uint64_t)*arg4_ptr);
- if (arg5_ptr)
- {
- s.Printf (", arg5 = 0x%" PRIx64, (uint64_t)*arg5_ptr);
- if (arg6_ptr)
- s.Printf (", arg6 = 0x%" PRIx64, (uint64_t)*arg6_ptr);
- }
- }
- }
- }
- }
+ for (int i = 0; i < args.size(); ++i)
+ s.Printf (", arg%d = 0x%" PRIx64, i + 1, args[i]);
s.PutCString (")");
log->PutCString(s.GetString().c_str());
}
@@ -352,62 +327,19 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
return false;
const RegisterInfo *reg_info = NULL;
- if (arg1_ptr)
+
+ if (args.size() > 6) // TODO handle more than 6 arguments
+ return false;
+
+ for (int i = 0; i < args.size(); ++i)
{
- reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
+ reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
if (log)
- log->Printf("About to write arg1 (0x%" PRIx64 ") into %s", (uint64_t)*arg1_ptr, reg_info->name);
-
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg1_ptr))
+ log->Printf("About to write arg%d (0x%" PRIx64 ") into %s", i + 1, args[i], reg_info->name);
+ if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
return false;
-
- if (arg2_ptr)
- {
- reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
- if (log)
- log->Printf("About to write arg2 (0x%" PRIx64 ") into %s", (uint64_t)*arg2_ptr, reg_info->name);
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg2_ptr))
- return false;
-
- if (arg3_ptr)
- {
- reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3);
- if (log)
- log->Printf("About to write arg3 (0x%" PRIx64 ") into %s", (uint64_t)*arg3_ptr, reg_info->name);
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg3_ptr))
- return false;
-
- if (arg4_ptr)
- {
- reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4);
- if (log)
- log->Printf("About to write arg4 (0x%" PRIx64 ") into %s", (uint64_t)*arg4_ptr, reg_info->name);
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg4_ptr))
- return false;
-
- if (arg5_ptr)
- {
- reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5);
- if (log)
- log->Printf("About to write arg5 (0x%" PRIx64 ") into %s", (uint64_t)*arg5_ptr, reg_info->name);
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg5_ptr))
- return false;
-
- if (arg6_ptr)
- {
- reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG6);
- if (log)
- log->Printf("About to write arg6 (0x%" PRIx64 ") into %s", (uint64_t)*arg6_ptr, reg_info->name);
- if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg6_ptr))
- return false;
- }
- }
- }
- }
- }
}
-
// First, align the SP
if (log)
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
index d9d6fd7af79a..5ccb6e5fa744 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -34,12 +34,7 @@ public:
lldb::addr_t sp,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
- lldb::addr_t *arg1_ptr = NULL,
- lldb::addr_t *arg2_ptr = NULL,
- lldb::addr_t *arg3_ptr = NULL,
- lldb::addr_t *arg4_ptr = NULL,
- lldb::addr_t *arg5_ptr = NULL,
- lldb::addr_t *arg6_ptr = NULL) const;
+ llvm::ArrayRef<lldb::addr_t> args) const;
virtual bool
GetArgumentValues (lldb_private::Thread &thread,
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index a3c294ae7a05..81e78847a1f3 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -1,4 +1,4 @@
-//===-- lldb_EmulateInstructionARM.h ------------------------------------*- C++ -*-===//
+//===-- lldb_EmulateInstructionARM.h ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index d18b4c75ae7b..f3c2d63729ae 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -445,6 +445,12 @@ ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
}
bool
+ItaniumABILanguageRuntime::ExceptionBreakpointsAreSet ()
+{
+ return m_cxx_exception_bp_sp && m_cxx_exception_bp_sp->IsEnabled();
+}
+
+bool
ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
{
if (!m_process)
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
index 6b2c437de252..cd0a4b2c15eb 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -71,6 +71,9 @@ namespace lldb_private {
ClearExceptionBreakpoints ();
virtual bool
+ ExceptionBreakpointsAreSet ();
+
+ virtual bool
ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
virtual lldb::BreakpointResolverSP
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 163e713bedb2..7bdacfe14cde 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -16,6 +16,7 @@
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
@@ -143,6 +144,44 @@ ELFRelocation::RelocSymbol64(const ELFRelocation &rel)
} // end anonymous namespace
+bool
+ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset)
+{
+ // Read all fields.
+ if (data.GetU32(offset, &n_namesz, 3) == NULL)
+ return false;
+
+ // The name field is required to be nul-terminated, and n_namesz
+ // includes the terminating nul in observed implementations (contrary
+ // to the ELF-64 spec). A special case is needed for cores generated
+ // by some older Linux versions, which write a note named "CORE"
+ // without a nul terminator and n_namesz = 4.
+ if (n_namesz == 4)
+ {
+ char buf[4];
+ if (data.ExtractBytes (*offset, 4, data.GetByteOrder(), buf) != 4)
+ return false;
+ if (strncmp (buf, "CORE", 4) == 0)
+ {
+ n_name = "CORE";
+ *offset += 4;
+ return true;
+ }
+ }
+
+ const char *cstr = data.GetCStr(offset, llvm::RoundUpToAlignment (n_namesz, 4));
+ if (cstr == NULL)
+ {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYMBOLS));
+ if (log)
+ log->Printf("Failed to parse note name lacking nul terminator");
+
+ return false;
+ }
+ n_name = cstr;
+ return true;
+}
+
//------------------------------------------------------------------
// Static methods.
//------------------------------------------------------------------
@@ -685,42 +724,26 @@ ParseNoteGNUBuildID(DataExtractor &data, lldb_private::UUID &uuid)
{
// Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id.
// BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId
- struct
- {
- uint32_t name_len; // Length of note name
- uint32_t desc_len; // Length of note descriptor
- uint32_t type; // Type of note (1 is ABI_TAG, 3 is BUILD_ID)
- } notehdr;
lldb::offset_t offset = 0;
static const uint32_t g_gnu_build_id = 3; // NT_GNU_BUILD_ID from elf.h
while (true)
{
- if (data.GetU32 (&offset, &notehdr, 3) == NULL)
+ ELFNote note = ELFNote();
+ if (!note.Parse(data, &offset))
return false;
- notehdr.name_len = llvm::RoundUpToAlignment (notehdr.name_len, 4);
- notehdr.desc_len = llvm::RoundUpToAlignment (notehdr.desc_len, 4);
-
- lldb::offset_t offset_next_note = offset + notehdr.name_len + notehdr.desc_len;
-
// 16 bytes is UUID|MD5, 20 bytes is SHA1
- if ((notehdr.type == g_gnu_build_id) && (notehdr.name_len == 4) &&
- (notehdr.desc_len == 16 || notehdr.desc_len == 20))
+ if (note.n_name == "GNU" && (note.n_type == g_gnu_build_id) &&
+ (note.n_descsz == 16 || note.n_descsz == 20))
{
- char name[4];
- if (data.GetU8 (&offset, name, 4) == NULL)
+ uint8_t uuidbuf[20];
+ if (data.GetU8 (&offset, &uuidbuf, note.n_descsz) == NULL)
return false;
- if (!strcmp(name, "GNU"))
- {
- uint8_t uuidbuf[20];
- if (data.GetU8 (&offset, &uuidbuf, notehdr.desc_len) == NULL)
- return false;
- uuid.SetBytes (uuidbuf, notehdr.desc_len);
- return true;
- }
+ uuid.SetBytes (uuidbuf, note.n_descsz);
+ return true;
}
- offset = offset_next_note;
+ offset += llvm::RoundUpToAlignment(note.n_descsz, 4);
}
return false;
}
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index ede886fb4f60..a2ab9b8f3703 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -20,6 +20,34 @@
#include "ELFHeader.h"
+struct ELFNote
+{
+ elf::elf_word n_namesz;
+ elf::elf_word n_descsz;
+ elf::elf_word n_type;
+
+ std::string n_name;
+
+ ELFNote() : n_namesz(0), n_descsz(0), n_type(0)
+ {
+ }
+
+ /// Parse an ELFNote entry from the given DataExtractor starting at position
+ /// \p offset.
+ ///
+ /// @param[in] data
+ /// The DataExtractor to read from.
+ ///
+ /// @param[in,out] offset
+ /// Pointer to an offset in the data. On return the offset will be
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+ /// True if the ELFRel entry was successfully read and false otherwise.
+ bool
+ Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+};
+
//------------------------------------------------------------------------------
/// @class ObjectFileELF
/// @brief Generic ELF object file reader.
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index 34316c484276..b5f92dcc3dcd 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -76,44 +76,56 @@ PlatformPOSIX::RunShellCommand (const char *command, // Shouldn't be N
}
}
-uint32_t
-PlatformPOSIX::MakeDirectory (const std::string &path,
- mode_t mode)
+Error
+PlatformPOSIX::MakeDirectory (const char *path, uint32_t file_permissions)
{
- if (IsHost())
- {
- return Host::MakeDirectory (path.c_str(), mode);
- }
- if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->MakeDirectory(path, mode);
- return Platform::MakeDirectory(path,mode);
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->MakeDirectory(path, file_permissions);
+ else
+ return Platform::MakeDirectory(path ,file_permissions);
+}
+
+Error
+PlatformPOSIX::GetFilePermissions (const char *path, uint32_t &file_permissions)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->GetFilePermissions(path, file_permissions);
+ else
+ return Platform::GetFilePermissions(path ,file_permissions);
+}
+
+Error
+PlatformPOSIX::SetFilePermissions (const char *path, uint32_t file_permissions)
+{
+ if (m_remote_platform_sp)
+ return m_remote_platform_sp->MakeDirectory(path, file_permissions);
+ else
+ return Platform::SetFilePermissions(path ,file_permissions);
}
lldb::user_id_t
PlatformPOSIX::OpenFile (const FileSpec& file_spec,
uint32_t flags,
- mode_t mode,
+ uint32_t mode,
Error &error)
{
if (IsHost())
- {
return Host::OpenFile(file_spec, flags, mode, error);
- }
- if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
- return Platform::OpenFile(file_spec, flags, mode, error);
+ else
+ return Platform::OpenFile(file_spec, flags, mode, error);
}
bool
PlatformPOSIX::CloseFile (lldb::user_id_t fd, Error &error)
{
if (IsHost())
- {
return Host::CloseFile(fd, error);
- }
- if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
return m_remote_platform_sp->CloseFile(fd, error);
- return Platform::CloseFile(fd, error);
+ else
+ return Platform::CloseFile(fd, error);
}
uint64_t
@@ -124,12 +136,11 @@ PlatformPOSIX::ReadFile (lldb::user_id_t fd,
Error &error)
{
if (IsHost())
- {
return Host::ReadFile(fd, offset, dst, dst_len, error);
- }
- if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
- return Platform::ReadFile(fd, offset, dst, dst_len, error);
+ else
+ return Platform::ReadFile(fd, offset, dst, dst_len, error);
}
uint64_t
@@ -140,13 +151,11 @@ PlatformPOSIX::WriteFile (lldb::user_id_t fd,
Error &error)
{
if (IsHost())
- {
return Host::WriteFile(fd, offset, src, src_len, error);
- }
- if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
-
- return Platform::WriteFile(fd, offset, src, src_len, error);
+ else
+ return Platform::WriteFile(fd, offset, src, src_len, error);
}
static uint32_t
@@ -184,6 +193,8 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
uint32_t uid,
uint32_t gid)
{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+
if (IsHost())
{
if (FileSpec::Equal(source, destination, true))
@@ -213,7 +224,7 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
return Error("unable to perform chown");
return Error();
}
- else if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
{
if (GetSupportsRSync())
{
@@ -244,7 +255,6 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
src_path.c_str(),
GetHostname(),
dst_path.c_str());
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[PutFile] Running command: %s\n", command.GetData());
int retcode;
@@ -263,20 +273,35 @@ PlatformPOSIX::PutFile (const lldb_private::FileSpec& source,
}
// if we are still here rsync has failed - let's try the slow way before giving up
}
+
+ if (log)
+ log->Printf ("PlatformPOSIX::PutFile(src='%s', dst='%s', uid=%u, gid=%u)",
+ source.GetPath().c_str(),
+ destination.GetPath().c_str(),
+ uid,
+ gid); // REMOVE THIS PRINTF PRIOR TO CHECKIN
// open
// read, write, read, write, ...
// close
// chown uid:gid dst
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf("[PutFile] Using block by block transfer....\n");
- File source_file(source, File::eOpenOptionRead, File::ePermissionsUserRW);
+ if (log)
+ log->Printf("[PutFile] Using block by block transfer....\n");
+
+ uint32_t source_open_options = File::eOpenOptionRead;
+ if (source.GetFileType() == FileSpec::eFileTypeSymbolicLink)
+ source_open_options |= File::eOpenoptionDontFollowSymlinks;
+
+ File source_file(source, source_open_options, lldb::eFilePermissionsUserRW);
+ Error error;
+ uint32_t permissions = source_file.GetPermissions(error);
+ if (permissions == 0)
+ permissions = lldb::eFilePermissionsFileDefault;
+
if (!source_file.IsValid())
return Error("unable to open source file");
- Error error;
lldb::user_id_t dest_file = OpenFile (destination,
File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
- File::ePermissionsUserRWX | File::ePermissionsGroupRX | File::ePermissionsWorldRX,
+ permissions,
error);
if (log)
log->Printf ("dest_file = %" PRIu64 "\n", dest_file);
@@ -314,45 +339,52 @@ lldb::user_id_t
PlatformPOSIX::GetFileSize (const FileSpec& file_spec)
{
if (IsHost())
- {
return Host::GetFileSize(file_spec);
- }
- if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
return m_remote_platform_sp->GetFileSize(file_spec);
- return Platform::GetFileSize(file_spec);
+ else
+ return Platform::GetFileSize(file_spec);
+}
+
+Error
+PlatformPOSIX::CreateSymlink(const char *src, const char *dst)
+{
+ if (IsHost())
+ return Host::Symlink(src, dst);
+ else if (m_remote_platform_sp)
+ return m_remote_platform_sp->CreateSymlink(src, dst);
+ else
+ return Platform::CreateSymlink(src, dst);
}
bool
PlatformPOSIX::GetFileExists (const FileSpec& file_spec)
{
if (IsHost())
- {
return file_spec.Exists();
- }
- if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
return m_remote_platform_sp->GetFileExists(file_spec);
- return Platform::GetFileExists(file_spec);
+ else
+ return Platform::GetFileExists(file_spec);
}
-uint32_t
-PlatformPOSIX::GetFilePermissions (const lldb_private::FileSpec &file_spec,
- lldb_private::Error &error)
+Error
+PlatformPOSIX::Unlink (const char *path)
{
if (IsHost())
- {
- return File::GetPermissions(file_spec.GetPath().c_str(), error);
- }
- if (IsRemote() && m_remote_platform_sp)
- return m_remote_platform_sp->GetFilePermissions(file_spec, error);
- return Platform::GetFilePermissions(file_spec, error);
-
+ return Host::Unlink (path);
+ else if (m_remote_platform_sp)
+ return m_remote_platform_sp->Unlink(path);
+ else
+ return Platform::Unlink(path);
}
-
lldb_private::Error
PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path */,
- const lldb_private::FileSpec& destination /* local file path */)
+ const lldb_private::FileSpec& destination /* local file path */)
{
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+
// Check the args, first.
std::string src_path (source.GetPath());
if (src_path.empty())
@@ -378,7 +410,7 @@ PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path
return Error("unable to perform copy");
return Error();
}
- else if (IsRemote() && m_remote_platform_sp)
+ else if (m_remote_platform_sp)
{
if (GetSupportsRSync())
{
@@ -403,7 +435,6 @@ PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path
m_remote_platform_sp->GetHostname(),
src_path.c_str(),
dst_path.c_str());
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[GetFile] Running command: %s\n", command.GetData());
int retcode;
@@ -421,22 +452,22 @@ PlatformPOSIX::GetFile (const lldb_private::FileSpec& source /* remote file path
// read/write, read/write, read/write, ...
// close src
// close dst
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf("[GetFile] Using block by block transfer....\n");
+ if (log)
+ log->Printf("[GetFile] Using block by block transfer....\n");
Error error;
user_id_t fd_src = OpenFile (source,
File::eOpenOptionRead,
- File::ePermissionsDefault,
+ lldb::eFilePermissionsFileDefault,
error);
if (fd_src == UINT64_MAX)
return Error("unable to open source file");
- uint32_t permissions = GetFilePermissions(source, error);
+ uint32_t permissions = 0;
+ error = GetFilePermissions(source.GetPath().c_str(), permissions);
if (permissions == 0)
- permissions = File::ePermissionsDefault;
+ permissions = lldb::eFilePermissionsFileDefault;
user_id_t fd_dst = Host::OpenFile(destination,
File::eOpenOptionCanCreate | File::eOpenOptionWrite | File::eOpenOptionTruncate,
@@ -539,3 +570,22 @@ PlatformPOSIX::CalculateMD5 (const FileSpec& file_spec,
return m_remote_platform_sp->CalculateMD5(file_spec, low, high);
return false;
}
+
+lldb_private::ConstString
+PlatformPOSIX::GetRemoteWorkingDirectory()
+{
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->GetRemoteWorkingDirectory();
+ else
+ return Platform::GetRemoteWorkingDirectory();
+}
+
+bool
+PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path)
+{
+ if (IsRemote() && m_remote_platform_sp)
+ return m_remote_platform_sp->SetRemoteWorkingDirectory(path);
+ else
+ return Platform::SetRemoteWorkingDirectory(path);
+}
+
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 4119e452bf7f..336e0f90fcad 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -43,7 +43,7 @@ public:
virtual lldb::user_id_t
OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode,
+ uint32_t mode,
lldb_private::Error &error);
virtual bool
@@ -68,9 +68,18 @@ public:
GetFileSize (const lldb_private::FileSpec& file_spec);
virtual lldb_private::Error
+ CreateSymlink(const char *src, const char *dst);
+
+ virtual lldb_private::Error
GetFile (const lldb_private::FileSpec& source,
const lldb_private::FileSpec& destination);
+ virtual lldb_private::ConstString
+ GetRemoteWorkingDirectory();
+
+ virtual bool
+ SetRemoteWorkingDirectory(const lldb_private::ConstString &path);
+
virtual lldb_private::Error
RunShellCommand (const char *command, // Shouldn't be NULL
const char *working_dir, // Pass NULL to use the current working directory
@@ -79,16 +88,20 @@ public:
std::string *command_output, // Pass NULL if you don't want the command output
uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
- virtual uint32_t
- MakeDirectory (const std::string &path,
- mode_t mode);
+ virtual lldb_private::Error
+ MakeDirectory (const char *path, uint32_t mode);
+ virtual lldb_private::Error
+ GetFilePermissions (const char *path, uint32_t &file_permissions);
+
+ virtual lldb_private::Error
+ SetFilePermissions (const char *path, uint32_t file_permissions);
+
virtual bool
GetFileExists (const lldb_private::FileSpec& file_spec);
- virtual uint32_t
- GetFilePermissions (const lldb_private::FileSpec &file_spec,
- lldb_private::Error &error);
+ virtual lldb_private::Error
+ Unlink (const char *path);
virtual std::string
GetPlatformSpecificConnectionInformation();
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 4aeec032d712..248abaf6fea7 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -194,6 +194,47 @@ PlatformRemoteGDBServer::GetRemoteSystemArchitecture ()
return m_gdb_client.GetSystemArchitecture();
}
+lldb_private::ConstString
+PlatformRemoteGDBServer::GetRemoteWorkingDirectory()
+{
+ if (IsConnected())
+ {
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ std::string cwd;
+ if (m_gdb_client.GetWorkingDir(cwd))
+ {
+ ConstString working_dir(cwd.c_str());
+ if (log)
+ log->Printf("PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'", working_dir.GetCString());
+ return working_dir;
+ }
+ else
+ {
+ return ConstString();
+ }
+ }
+ else
+ {
+ return Platform::GetRemoteWorkingDirectory();
+ }
+}
+
+bool
+PlatformRemoteGDBServer::SetRemoteWorkingDirectory(const lldb_private::ConstString &path)
+{
+ if (IsConnected())
+ {
+ // Clear the working directory it case it doesn't get set correctly. This will
+ // for use to re-read it
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')", path.GetCString());
+ return m_gdb_client.SetWorkingDir(path.GetCString()) == 0;
+ }
+ else
+ return Platform::SetRemoteWorkingDirectory(path);
+}
+
bool
PlatformRemoteGDBServer::IsConnected () const
{
@@ -220,8 +261,10 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args)
{
if (m_gdb_client.HandshakeWithServer(&error))
{
- m_gdb_client.QueryNoAckModeSupported();
m_gdb_client.GetHostInfo();
+ // If a working directory was set prior to connecting, send it down now
+ if (m_working_dir)
+ m_gdb_client.SetWorkingDir(m_working_dir.GetCString());
#if 0
m_gdb_client.TestPacketSpeed(10000);
#endif
@@ -229,6 +272,8 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args)
else
{
m_gdb_client.Disconnect();
+ if (error.Success())
+ error.SetErrorString("handshake failed");
}
}
}
@@ -237,11 +282,6 @@ PlatformRemoteGDBServer::ConnectRemote (Args& args)
error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
}
}
-
- if (error.Success())
- {
-
- }
return error;
}
@@ -324,7 +364,6 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
}
// Send the environment and the program + arguments after we connect
- const char **argv = launch_info.GetArguments().GetConstArgumentVector();
const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector();
if (envp)
@@ -343,7 +382,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
m_gdb_client.SendLaunchArchPacket(arch_triple);
const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5);
- int arg_packet_err = m_gdb_client.SendArgumentsPacket (argv);
+ int arg_packet_err = m_gdb_client.SendArgumentsPacket (launch_info);
m_gdb_client.SetPacketTimeout (old_packet_timeout);
if (arg_packet_err == 0)
{
@@ -367,6 +406,80 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
}
lldb::ProcessSP
+PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ lldb_private::Listener &listener,
+ lldb_private::Error &error)
+{
+ lldb::ProcessSP process_sp;
+ if (IsRemote())
+ {
+ if (IsConnected())
+ {
+ lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid);
+
+ if (port == 0)
+ {
+ error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
+ }
+ else
+ {
+ if (target == NULL)
+ {
+ TargetSP new_target_sp;
+
+ error = debugger.GetTargetList().CreateTarget (debugger,
+ NULL,
+ NULL,
+ false,
+ NULL,
+ new_target_sp);
+ target = new_target_sp.get();
+ }
+ else
+ error.Clear();
+
+ if (target && error.Success())
+ {
+ debugger.GetTargetList().SetSelectedTarget(target);
+
+ // The darwin always currently uses the GDB remote debugger plug-in
+ // so even when debugging locally we are debugging remotely!
+ process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
+
+ if (process_sp)
+ {
+ char connect_url[256];
+ const char *override_hostname = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
+ const char *port_offset_c_str = getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
+ int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
+ const int connect_url_len = ::snprintf (connect_url,
+ sizeof(connect_url),
+ "connect://%s:%u",
+ override_hostname ? override_hostname : GetHostname (),
+ port + port_offset);
+ assert (connect_url_len < (int)sizeof(connect_url));
+ error = process_sp->ConnectRemote (NULL, connect_url);
+ if (error.Success())
+ error = process_sp->Launch(launch_info);
+ else if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ m_gdb_client.KillSpawnedProcess(debugserver_pid);
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("not connected to remote gdb server");
+ }
+ }
+ return process_sp;
+
+}
+
+lldb::ProcessSP
PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
Debugger &debugger,
Target *target, // Can be NULL, if NULL create a new target, else use existing one
@@ -441,17 +554,42 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
return process_sp;
}
-uint32_t
-PlatformRemoteGDBServer::MakeDirectory (const std::string &path,
- mode_t mode)
+Error
+PlatformRemoteGDBServer::MakeDirectory (const char *path, uint32_t mode)
{
- return m_gdb_client.MakeDirectory(path,mode);
+ Error error = m_gdb_client.MakeDirectory(path,mode);
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) error = %u (%s)", path, mode, error.GetError(), error.AsCString());
+ return error;
}
+
+Error
+PlatformRemoteGDBServer::GetFilePermissions (const char *path, uint32_t &file_permissions)
+{
+ Error error = m_gdb_client.GetFilePermissions(path, file_permissions);
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::GetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", path, file_permissions, error.GetError(), error.AsCString());
+ return error;
+}
+
+Error
+PlatformRemoteGDBServer::SetFilePermissions (const char *path, uint32_t file_permissions)
+{
+ Error error = m_gdb_client.SetFilePermissions(path, file_permissions);
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::SetFilePermissions(path='%s', file_permissions=%o) error = %u (%s)", path, file_permissions, error.GetError(), error.AsCString());
+ return error;
+}
+
+
lldb::user_id_t
PlatformRemoteGDBServer::OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode,
+ uint32_t mode,
Error &error)
{
return m_gdb_client.OpenFile (file_spec, flags, mode, error);
@@ -469,13 +607,6 @@ PlatformRemoteGDBServer::GetFileSize (const lldb_private::FileSpec& file_spec)
return m_gdb_client.GetFileSize(file_spec);
}
-uint32_t
-PlatformRemoteGDBServer::GetFilePermissions (const lldb_private::FileSpec &file_spec,
- lldb_private::Error &error)
-{
- return m_gdb_client.GetFilePermissions(file_spec, error);
-}
-
uint64_t
PlatformRemoteGDBServer::ReadFile (lldb::user_id_t fd,
uint64_t offset,
@@ -505,6 +636,27 @@ PlatformRemoteGDBServer::PutFile (const lldb_private::FileSpec& source,
return Platform::PutFile(source,destination,uid,gid);
}
+Error
+PlatformRemoteGDBServer::CreateSymlink (const char *src, // The name of the link is in src
+ const char *dst) // The symlink points to dst
+{
+ Error error = m_gdb_client.CreateSymlink (src, dst);
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') error = %u (%s)", src, dst, error.GetError(), error.AsCString());
+ return error;
+}
+
+Error
+PlatformRemoteGDBServer::Unlink (const char *path)
+{
+ Error error = m_gdb_client.Unlink (path);
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf ("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)", path, error.GetError(), error.AsCString());
+ return error;
+}
+
bool
PlatformRemoteGDBServer::GetFileExists (const lldb_private::FileSpec& file_spec)
{
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 70db6bafacd2..808fb5ed61cc 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -89,6 +89,13 @@ public:
LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
virtual lldb::ProcessSP
+ DebugProcess (lldb_private::ProcessLaunchInfo &launch_info,
+ lldb_private::Debugger &debugger,
+ lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ lldb_private::Listener &listener,
+ lldb_private::Error &error);
+
+ virtual lldb::ProcessSP
Attach (lldb_private::ProcessAttachInfo &attach_info,
lldb_private::Debugger &debugger,
lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one
@@ -115,6 +122,13 @@ public:
virtual lldb_private::ArchSpec
GetRemoteSystemArchitecture ();
+ virtual lldb_private::ConstString
+ GetRemoteWorkingDirectory();
+
+ virtual bool
+ SetRemoteWorkingDirectory(const lldb_private::ConstString &path);
+
+
// Remote subclasses should override this and return a valid instance
// name if connected.
virtual const char *
@@ -135,14 +149,20 @@ public:
virtual lldb_private::Error
DisconnectRemote ();
- virtual uint32_t
- MakeDirectory (const std::string &path,
- mode_t mode);
+ virtual lldb_private::Error
+ MakeDirectory (const char *path, uint32_t file_permissions);
+
+ virtual lldb_private::Error
+ GetFilePermissions (const char *path, uint32_t &file_permissions);
+
+ virtual lldb_private::Error
+ SetFilePermissions (const char *path, uint32_t file_permissions);
+
virtual lldb::user_id_t
OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
- mode_t mode,
+ uint32_t mode,
lldb_private::Error &error);
virtual bool
@@ -172,12 +192,14 @@ public:
uint32_t uid = UINT32_MAX,
uint32_t gid = UINT32_MAX);
+ virtual lldb_private::Error
+ CreateSymlink (const char *src, const char *dst);
+
virtual bool
GetFileExists (const lldb_private::FileSpec& file_spec);
-
- virtual uint32_t
- GetFilePermissions (const lldb_private::FileSpec &file_spec,
- lldb_private::Error &error);
+
+ virtual lldb_private::Error
+ Unlink (const char *path);
virtual lldb_private::Error
RunShellCommand (const char *command, // Shouldn't be NULL
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 3833fa6baf85..ac5357916501 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -465,13 +465,12 @@ WriteFPROperation::Execute(ProcessMonitor *monitor)
class ResumeOperation : public Operation
{
public:
- ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) :
- m_tid(tid), m_signo(signo), m_result(result) { }
+ ResumeOperation(uint32_t signo, bool &result) :
+ m_signo(signo), m_result(result) { }
void Execute(ProcessMonitor *monitor);
private:
- lldb::tid_t m_tid;
uint32_t m_signo;
bool &m_result;
};
@@ -479,17 +478,18 @@ private:
void
ResumeOperation::Execute(ProcessMonitor *monitor)
{
+ lldb::pid_t pid = monitor->GetPID();
int data = 0;
if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
data = m_signo;
- if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data))
+ if (PTRACE(PT_CONTINUE, pid, (caddr_t)1, data))
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (log)
- log->Printf ("ResumeOperation (%" PRIu64 ") failed: %s", m_tid, strerror(errno));
+ log->Printf ("ResumeOperation (%" PRIu64 ") failed: %s", pid, strerror(errno));
m_result = false;
}
else
@@ -502,13 +502,12 @@ ResumeOperation::Execute(ProcessMonitor *monitor)
class SingleStepOperation : public Operation
{
public:
- SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result)
- : m_tid(tid), m_signo(signo), m_result(result) { }
+ SingleStepOperation(uint32_t signo, bool &result)
+ : m_signo(signo), m_result(result) { }
void Execute(ProcessMonitor *monitor);
private:
- lldb::tid_t m_tid;
uint32_t m_signo;
bool &m_result;
};
@@ -516,12 +515,13 @@ private:
void
SingleStepOperation::Execute(ProcessMonitor *monitor)
{
+ lldb::pid_t pid = monitor->GetPID();
int data = 0;
if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
data = m_signo;
- if (PTRACE(PT_STEP, m_tid, NULL, data))
+ if (PTRACE(PT_STEP, pid, NULL, data))
m_result = false;
else
m_result = true;
@@ -585,7 +585,7 @@ EventMessageOperation::Execute(ProcessMonitor *monitor)
m_result = false;
else {
if (plwp.pl_flags & PL_FLAG_FORKED) {
- m_message = (unsigned long *)plwp.pl_child_pid;
+ *m_message = plwp.pl_child_pid;
m_result = true;
} else
m_result = false;
@@ -953,7 +953,7 @@ ProcessMonitor::Launch(LaunchArgs *args)
}
goto FINISH;
}
- assert(WIFSTOPPED(status) && wpid == pid &&
+ assert(WIFSTOPPED(status) && wpid == (::pid_t)pid &&
"Could not sync with inferior process.");
#ifdef notyet
@@ -1338,8 +1338,6 @@ ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info)
void
ProcessMonitor::ServeOperation(OperationArgs *args)
{
- int status;
-
ProcessMonitor *monitor = args->m_monitor;
// We are finised with the arguments and are ready to go. Sync with the
@@ -1467,15 +1465,15 @@ ProcessMonitor::ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value)
}
bool
-ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
+ProcessMonitor::Resume(lldb::tid_t unused, uint32_t signo)
{
bool result;
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
if (log)
- log->Printf ("ProcessMonitor::%s() resuming thread = %" PRIu64 " with signal %s", __FUNCTION__, tid,
+ log->Printf ("ProcessMonitor::%s() resuming pid %" PRIu64 " with signal %s", __FUNCTION__, GetPID(),
m_process->GetUnixSignals().GetSignalAsCString (signo));
- ResumeOperation op(tid, signo, result);
+ ResumeOperation op(signo, result);
DoOperation(&op);
if (log)
log->Printf ("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false");
@@ -1483,10 +1481,10 @@ ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
}
bool
-ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo)
+ProcessMonitor::SingleStep(lldb::tid_t unused, uint32_t signo)
{
bool result;
- SingleStepOperation op(tid, signo, result);
+ SingleStepOperation op(signo, result);
DoOperation(&op);
return result;
}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 4a9b48370444..44219c4eb9e3 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -175,15 +175,15 @@ public:
bool
GetEventMessage(lldb::tid_t tid, unsigned long *message);
- /// Resumes the given thread. If @p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ /// Resumes the process. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
bool
- Resume(lldb::tid_t tid, uint32_t signo);
+ Resume(lldb::tid_t unused, uint32_t signo);
- /// Single steps the given thread. If @p signo is anything but
- /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+ /// Single steps the process. If @p signo is anything but
+ /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
bool
- SingleStep(lldb::tid_t tid, uint32_t signo);
+ SingleStep(lldb::tid_t unused, uint32_t signo);
/// Sends the inferior process a PTRACE_KILL signal. The inferior will
/// still exists and can be interrogated. Once resumed it will exit as
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
index 98e0bce68678..f833c9b47520 100644
--- a/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -377,8 +377,6 @@ RegisterContextPOSIXProcessMonitor_x86_64::WriteAllRegisterValues(const DataBuff
success = WriteFPR();
if (success)
{
- success = true;
-
if (GetFPRType() == eXSAVE)
{
ByteOrder byte_order = GetByteOrder();
diff --git a/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
index 1bab88cd5727..86abdba68db6 100644
--- a/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
+++ b/source/Plugins/Process/POSIX/RegisterInfos_x86_64.h
@@ -94,14 +94,14 @@ g_register_infos_x86_64[] =
// General purpose registers. GCC, DWARF, Generic, GDB
DEFINE_GPR(rax, NULL, gcc_dwarf_rax_x86_64, gcc_dwarf_rax_x86_64, LLDB_INVALID_REGNUM, gdb_rax_x86_64),
DEFINE_GPR(rbx, NULL, gcc_dwarf_rbx_x86_64, gcc_dwarf_rbx_x86_64, LLDB_INVALID_REGNUM, gdb_rbx_x86_64),
- DEFINE_GPR(rcx, "arg4", gcc_dwarf_rcx_x86_64, gcc_dwarf_rcx_x86_64, LLDB_INVALID_REGNUM, gdb_rcx_x86_64),
- DEFINE_GPR(rdx, "arg3", gcc_dwarf_rdx_x86_64, gcc_dwarf_rdx_x86_64, LLDB_INVALID_REGNUM, gdb_rdx_x86_64),
- DEFINE_GPR(rdi, "arg1", gcc_dwarf_rdi_x86_64, gcc_dwarf_rdi_x86_64, LLDB_INVALID_REGNUM, gdb_rdi_x86_64),
- DEFINE_GPR(rsi, "arg2", gcc_dwarf_rsi_x86_64, gcc_dwarf_rsi_x86_64, LLDB_INVALID_REGNUM, gdb_rsi_x86_64),
+ DEFINE_GPR(rcx, "arg4", gcc_dwarf_rcx_x86_64, gcc_dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG4, gdb_rcx_x86_64),
+ DEFINE_GPR(rdx, "arg3", gcc_dwarf_rdx_x86_64, gcc_dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG3, gdb_rdx_x86_64),
+ DEFINE_GPR(rdi, "arg1", gcc_dwarf_rdi_x86_64, gcc_dwarf_rdi_x86_64, LLDB_REGNUM_GENERIC_ARG1, gdb_rdi_x86_64),
+ DEFINE_GPR(rsi, "arg2", gcc_dwarf_rsi_x86_64, gcc_dwarf_rsi_x86_64, LLDB_REGNUM_GENERIC_ARG2, gdb_rsi_x86_64),
DEFINE_GPR(rbp, "fp", gcc_dwarf_rbp_x86_64, gcc_dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP, gdb_rbp_x86_64),
DEFINE_GPR(rsp, "sp", gcc_dwarf_rsp_x86_64, gcc_dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP, gdb_rsp_x86_64),
- DEFINE_GPR(r8, "arg5", gcc_dwarf_r8_x86_64, gcc_dwarf_r8_x86_64, LLDB_INVALID_REGNUM, gdb_r8_x86_64),
- DEFINE_GPR(r9, "arg6", gcc_dwarf_r9_x86_64, gcc_dwarf_r9_x86_64, LLDB_INVALID_REGNUM, gdb_r9_x86_64),
+ DEFINE_GPR(r8, "arg5", gcc_dwarf_r8_x86_64, gcc_dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG5, gdb_r8_x86_64),
+ DEFINE_GPR(r9, "arg6", gcc_dwarf_r9_x86_64, gcc_dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG6, gdb_r9_x86_64),
DEFINE_GPR(r10, NULL, gcc_dwarf_r10_x86_64, gcc_dwarf_r10_x86_64, LLDB_INVALID_REGNUM, gdb_r10_x86_64),
DEFINE_GPR(r11, NULL, gcc_dwarf_r11_x86_64, gcc_dwarf_r11_x86_64, LLDB_INVALID_REGNUM, gdb_r11_x86_64),
DEFINE_GPR(r12, NULL, gcc_dwarf_r12_x86_64, gcc_dwarf_r12_x86_64, LLDB_INVALID_REGNUM, gdb_r12_x86_64),
diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp
new file mode 100644
index 000000000000..521136295fd5
--- /dev/null
+++ b/source/Plugins/Process/Utility/HistoryThread.cpp
@@ -0,0 +1,95 @@
+//===-- HistoryThread.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+
+#include "Plugins/Process/Utility/HistoryUnwind.h"
+#include "Plugins/Process/Utility/HistoryThread.h"
+#include "Plugins/Process/Utility/RegisterContextHistory.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Target/StackFrameList.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+HistoryThread::HistoryThread (lldb_private::Process &process,
+ lldb::tid_t tid,
+ std::vector<lldb::addr_t> pcs,
+ uint32_t stop_id,
+ bool stop_id_is_valid) :
+ Thread (process, LLDB_INVALID_THREAD_ID),
+ m_framelist_mutex(),
+ m_framelist(),
+ m_pcs (pcs),
+ m_stop_id (stop_id),
+ m_stop_id_is_valid (stop_id_is_valid),
+ m_extended_unwind_token (LLDB_INVALID_ADDRESS),
+ m_queue_name (),
+ m_thread_name (),
+ m_originating_unique_thread_id (tid),
+ m_queue_id (LLDB_INVALID_QUEUE_ID)
+{
+ m_unwinder_ap.reset (new HistoryUnwind (*this, pcs, stop_id, stop_id_is_valid));
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p HistoryThread::HistoryThread", this);
+}
+
+HistoryThread::~HistoryThread ()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p HistoryThread::~HistoryThread (tid=0x%" PRIx64 ")", this, GetID());
+ DestroyThread();
+}
+
+lldb::RegisterContextSP
+HistoryThread::GetRegisterContext ()
+{
+ RegisterContextSP rctx ;
+ if (m_pcs.size() > 0)
+ {
+ rctx.reset (new RegisterContextHistory (*this, 0, GetProcess()->GetAddressByteSize(), m_pcs[0]));
+ }
+ return rctx;
+
+}
+
+lldb::RegisterContextSP
+HistoryThread::CreateRegisterContextForFrame (StackFrame *frame)
+{
+ return m_unwinder_ap->CreateRegisterContextForFrame (frame);
+}
+
+lldb::StackFrameListSP
+HistoryThread::GetStackFrameList ()
+{
+ Mutex::Locker (m_framelist_mutex);
+ if (m_framelist.get() == NULL)
+ {
+ m_framelist.reset (new StackFrameList (*this, StackFrameListSP(), true));
+ }
+
+ return m_framelist;
+}
+
+uint32_t
+HistoryThread::GetExtendedBacktraceOriginatingIndexID ()
+{
+ if (m_originating_unique_thread_id != LLDB_INVALID_THREAD_ID)
+ {
+ if (GetProcess()->HasAssignedIndexIDToThread (m_originating_unique_thread_id))
+ {
+ return GetProcess()->AssignIndexIDToThread (m_originating_unique_thread_id);
+ }
+ }
+ return LLDB_INVALID_THREAD_ID;
+}
diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h
new file mode 100644
index 000000000000..01fdd1608706
--- /dev/null
+++ b/source/Plugins/Process/Utility/HistoryThread.h
@@ -0,0 +1,114 @@
+//===-- HistoryThread.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_HistoryThread_h_
+#define liblldb_HistoryThread_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/Event.h"
+#include "lldb/Core/UserID.h"
+#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/StackFrameList.h"
+#include "lldb/Target/Thread.h"
+
+namespace lldb_private {
+
+class HistoryThread : public lldb_private::Thread
+{
+public:
+ HistoryThread (lldb_private::Process &process, lldb::tid_t tid, std::vector<lldb::addr_t> pcs, uint32_t stop_id, bool stop_id_is_valid);
+
+ virtual ~HistoryThread ();
+
+ virtual lldb::RegisterContextSP
+ GetRegisterContext ();
+
+ virtual lldb::RegisterContextSP
+ CreateRegisterContextForFrame (StackFrame *frame);
+
+ virtual void
+ RefreshStateAfterStop() { }
+
+ bool
+ CalculateStopInfo () { return false; }
+
+ void
+ SetExtendedBacktraceToken (uint64_t token)
+ {
+ m_extended_unwind_token = token;
+ }
+
+ uint64_t
+ GetExtendedBacktraceToken ()
+ {
+ return m_extended_unwind_token;
+ }
+
+ const char *
+ GetQueueName ()
+ {
+ return m_queue_name.c_str();
+ }
+
+ void
+ SetQueueName (const char *name)
+ {
+ m_queue_name = name;
+ }
+
+ lldb::queue_id_t
+ GetQueueID ()
+ {
+ return m_queue_id;
+ }
+
+ void
+ SetQueueID (lldb::queue_id_t queue)
+ {
+ m_queue_id = queue;
+ }
+
+ const char *
+ GetThreadName ()
+ {
+ return m_thread_name.c_str();
+ }
+
+ uint32_t
+ GetExtendedBacktraceOriginatingIndexID ();
+
+ void
+ SetThreadName (const char *name)
+ {
+ m_thread_name = name;
+ }
+
+protected:
+ virtual lldb::StackFrameListSP
+ GetStackFrameList ();
+
+ mutable Mutex m_framelist_mutex;
+ lldb::StackFrameListSP m_framelist;
+ std::vector<lldb::addr_t> m_pcs;
+ uint32_t m_stop_id;
+ bool m_stop_id_is_valid;
+
+ uint64_t m_extended_unwind_token;
+ std::string m_queue_name;
+ std::string m_thread_name;
+ lldb::tid_t m_originating_unique_thread_id;
+ lldb::queue_id_t m_queue_id;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_HistoryThread_h_
diff --git a/source/Plugins/Process/Utility/HistoryUnwind.cpp b/source/Plugins/Process/Utility/HistoryUnwind.cpp
new file mode 100644
index 000000000000..86665fd17b13
--- /dev/null
+++ b/source/Plugins/Process/Utility/HistoryUnwind.cpp
@@ -0,0 +1,79 @@
+//===-- HistoryUnwind.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+
+#include "Plugins/Process/Utility/RegisterContextHistory.h"
+#include "Plugins/Process/Utility/HistoryUnwind.h"
+
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+HistoryUnwind::HistoryUnwind (Thread &thread,
+ std::vector<lldb::addr_t> pcs,
+ uint32_t stop_id,
+ bool stop_id_is_valid) :
+ Unwind (thread),
+ m_pcs (pcs),
+ m_stop_id (stop_id),
+ m_stop_id_is_valid (stop_id_is_valid)
+{
+}
+
+HistoryUnwind::~HistoryUnwind ()
+{
+}
+
+void
+HistoryUnwind::DoClear ()
+{
+ Mutex::Locker locker(m_unwind_mutex);
+ m_pcs.clear();
+ m_stop_id_is_valid = false;
+}
+
+lldb::RegisterContextSP
+HistoryUnwind::DoCreateRegisterContextForFrame (StackFrame *frame)
+{
+ RegisterContextSP rctx;
+ if (frame)
+ {
+ addr_t pc = frame->GetFrameCodeAddress().GetLoadAddress (&frame->GetThread()->GetProcess()->GetTarget());
+ if (pc != LLDB_INVALID_ADDRESS)
+ {
+ rctx.reset (new RegisterContextHistory (*frame->GetThread().get(), frame->GetConcreteFrameIndex(),
+ frame->GetThread()->GetProcess()->GetAddressByteSize(), pc));
+ }
+ }
+ return rctx;
+}
+
+bool
+HistoryUnwind::DoGetFrameInfoAtIndex (uint32_t frame_idx, lldb::addr_t& cfa, lldb::addr_t& pc)
+{
+ Mutex::Locker (m_unwind_mutex);
+ if (frame_idx < m_pcs.size())
+ {
+ cfa = frame_idx;
+ pc = m_pcs[frame_idx];
+ return true;
+ }
+ return false;
+}
+
+uint32_t
+HistoryUnwind::DoGetFrameCount ()
+{
+ return m_pcs.size();
+}
diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h
new file mode 100644
index 000000000000..0661b8028608
--- /dev/null
+++ b/source/Plugins/Process/Utility/HistoryUnwind.h
@@ -0,0 +1,51 @@
+//===-- HistoryUnwind.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_HistoryUnwind_h_
+#define liblldb_HistoryUnwind_h_
+
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Unwind.h"
+
+namespace lldb_private {
+
+class HistoryUnwind : public lldb_private::Unwind
+{
+public:
+ HistoryUnwind (Thread &thread, std::vector<lldb::addr_t> pcs, uint32_t stop_id, bool stop_id_is_valid);
+
+ virtual ~HistoryUnwind ();
+
+protected:
+ void
+ DoClear();
+
+ lldb::RegisterContextSP
+ DoCreateRegisterContextForFrame (StackFrame *frame);
+
+ bool
+ DoGetFrameInfoAtIndex (uint32_t frame_idx,
+ lldb::addr_t& cfa,
+ lldb::addr_t& pc);
+ uint32_t
+ DoGetFrameCount ();
+
+private:
+
+ std::vector<lldb::addr_t> m_pcs;
+ uint32_t m_stop_id;
+ bool m_stop_id_is_valid;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_HistoryUnwind_h_
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 8b22d6457ada..6d1b04f7f1a7 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -59,11 +59,13 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
{
const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
const bool use_inline_block_range = false;
- const bool stop_other_threads = true;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
- const bool try_all_threads = true;
- const uint32_t timeout_usec = 500000;
+ EvaluateExpressionOptions options;
+ options.SetStopOthers(true);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTryAllThreads(true);
+ options.SetDebug (false);
+ options.SetTimeoutUsec(500000);
addr_t prot_arg, flags_arg = 0;
if (prot == eMmapProtNone)
@@ -88,19 +90,13 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
{
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
ThreadPlanCallFunction *call_function_thread_plan
= new ThreadPlanCallFunction (*thread,
mmap_range.GetBaseAddress(),
clang_void_ptr_type,
- stop_other_threads,
- unwind_on_error,
- ignore_breakpoints,
- &addr,
- &length,
- &prot_arg,
- &flags_arg,
- &fd,
- &offset);
+ args,
+ options);
lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
if (call_plan_sp)
{
@@ -115,12 +111,8 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
ExecutionContext exe_ctx;
frame->CalculateExecutionContext (exe_ctx);
ExecutionResults result = process->RunThreadPlan (exe_ctx,
- call_plan_sp,
- stop_other_threads,
- try_all_threads,
- unwind_on_error,
- ignore_breakpoints,
- timeout_usec,
+ call_plan_sp,
+ options,
error_strm);
if (result == eExecutionCompleted)
{
@@ -169,56 +161,52 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
SymbolContext sc;
if (sc_list.GetContextAtIndex(0, sc))
{
- const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
- const bool use_inline_block_range = false;
- const bool stop_other_threads = true;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
- const bool try_all_threads = true;
- const uint32_t timeout_usec = 500000;
+ const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
+ const bool use_inline_block_range = false;
+ EvaluateExpressionOptions options;
+ options.SetStopOthers(true);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTryAllThreads(true);
+ options.SetDebug (false);
+ options.SetTimeoutUsec(500000);
- AddressRange munmap_range;
- if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
- {
- lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+ AddressRange munmap_range;
+ if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
+ {
+ lldb::addr_t args[] = { addr, length };
+ lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
munmap_range.GetBaseAddress(),
ClangASTType(),
- stop_other_threads,
- unwind_on_error,
- ignore_breakpoints,
- &addr,
- &length));
- if (call_plan_sp)
- {
- StreamFile error_strm;
- // This plan is a utility plan, so set it to discard itself when done.
- call_plan_sp->SetIsMasterPlan (true);
- call_plan_sp->SetOkayToDiscard(true);
+ args,
+ options));
+ if (call_plan_sp)
+ {
+ StreamFile error_strm;
+ // This plan is a utility plan, so set it to discard itself when done.
+ call_plan_sp->SetIsMasterPlan (true);
+ call_plan_sp->SetOkayToDiscard(true);
- StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
- if (frame)
- {
- ExecutionContext exe_ctx;
- frame->CalculateExecutionContext (exe_ctx);
- ExecutionResults result = process->RunThreadPlan (exe_ctx,
- call_plan_sp,
- stop_other_threads,
- try_all_threads,
- unwind_on_error,
- ignore_breakpoints,
- timeout_usec,
- error_strm);
- if (result == eExecutionCompleted)
- {
- return true;
- }
- }
- }
- }
- }
- }
+ StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
+ if (frame)
+ {
+ ExecutionContext exe_ctx;
+ frame->CalculateExecutionContext (exe_ctx);
+ ExecutionResults result = process->RunThreadPlan (exe_ctx,
+ call_plan_sp,
+ options,
+ error_strm);
+ if (result == eExecutionCompleted)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
- return false;
+ return false;
}
bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
@@ -226,11 +214,13 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
if (thread == NULL || address == NULL)
return false;
- const bool stop_other_threads = true;
- const bool unwind_on_error = true;
- const bool ignore_breakpoints = true;
- const bool try_all_threads = true;
- const uint32_t timeout_usec = 500000;
+ EvaluateExpressionOptions options;
+ options.SetStopOthers(true);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetTryAllThreads(true);
+ options.SetDebug (false);
+ options.SetTimeoutUsec(500000);
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
@@ -238,9 +228,8 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
= new ThreadPlanCallFunction (*thread,
*address,
clang_void_ptr_type,
- stop_other_threads,
- unwind_on_error,
- ignore_breakpoints);
+ llvm::ArrayRef<addr_t>(),
+ options);
lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
if (call_plan_sp)
{
@@ -256,11 +245,7 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
frame->CalculateExecutionContext (exe_ctx);
ExecutionResults result = process->RunThreadPlan (exe_ctx,
call_plan_sp,
- stop_other_threads,
- try_all_threads,
- unwind_on_error,
- ignore_breakpoints,
- timeout_usec,
+ options,
error_strm);
if (result == eExecutionCompleted)
{
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
new file mode 100644
index 000000000000..b7adb202ba49
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
@@ -0,0 +1,138 @@
+//===-- RegisterContextHistory.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "RegisterContextHistory.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextHistory::RegisterContextHistory (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size, addr_t pc_value) :
+RegisterContext (thread, concrete_frame_idx),
+ m_pc_value (pc_value)
+{
+ m_reg_set0.name = "General Purpose Registers";
+ m_reg_set0.short_name = "GPR";
+ m_reg_set0.num_registers = 1;
+ m_reg_set0.registers = new uint32_t(0);
+
+ m_pc_reg_info.name = "pc";
+ m_pc_reg_info.alt_name = "pc";
+ m_pc_reg_info.byte_offset = 0;
+ m_pc_reg_info.byte_size = address_byte_size;
+ m_pc_reg_info.encoding = eEncodingUint;
+ m_pc_reg_info.format = eFormatPointer;
+ m_pc_reg_info.invalidate_regs = NULL;
+ m_pc_reg_info.value_regs = NULL;
+ m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
+ m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM;
+ m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;
+}
+
+RegisterContextHistory::~RegisterContextHistory ()
+{
+ delete m_reg_set0.registers;
+ delete m_pc_reg_info.invalidate_regs;
+ delete m_pc_reg_info.value_regs;
+}
+
+void
+RegisterContextHistory::InvalidateAllRegisters () {}
+
+size_t
+RegisterContextHistory::GetRegisterCount ()
+{
+ return 1;
+}
+
+const lldb_private::RegisterInfo *
+RegisterContextHistory::GetRegisterInfoAtIndex (size_t reg)
+{
+ if (reg)
+ return NULL;
+ return &m_pc_reg_info;
+}
+
+size_t
+RegisterContextHistory::GetRegisterSetCount ()
+{
+ return 1;
+}
+
+const lldb_private::RegisterSet *
+RegisterContextHistory::GetRegisterSet (size_t reg_set)
+{
+ if (reg_set)
+ return NULL;
+ return &m_reg_set0;
+}
+
+bool
+RegisterContextHistory::ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value)
+{
+ if (!reg_info)
+ return false;
+ uint32_t reg_number = reg_info->kinds[eRegisterKindGeneric];
+ if (reg_number == LLDB_REGNUM_GENERIC_PC)
+ {
+ value.SetUInt(m_pc_value, reg_info->byte_size);
+ return true;
+ }
+ return false;
+}
+
+bool
+RegisterContextHistory::WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value)
+{
+ return false;
+}
+
+bool
+RegisterContextHistory::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+bool
+RegisterContextHistory::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+ return false;
+}
+
+uint32_t
+RegisterContextHistory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+ if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC)
+ return 0;
+ return LLDB_INVALID_REGNUM;
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.h b/source/Plugins/Process/Utility/RegisterContextHistory.h
new file mode 100644
index 000000000000..58e16080b52e
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.h
@@ -0,0 +1,79 @@
+//===-- RegisterContextHistory.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_RegisterContextHistory_h_
+#define lldb_RegisterContextHistory_h_
+
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+namespace lldb_private {
+
+class RegisterContextHistory : public lldb_private::RegisterContext
+{
+public:
+ typedef std::shared_ptr<RegisterContextHistory> SharedPtr;
+
+ RegisterContextHistory (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size, lldb::addr_t pc_value);
+
+ ///
+ // pure virtual functions from the base class that we must implement
+ ///
+
+ virtual
+ ~RegisterContextHistory ();
+
+ virtual void
+ InvalidateAllRegisters ();
+
+ virtual size_t
+ GetRegisterCount ();
+
+ virtual const lldb_private::RegisterInfo *
+ GetRegisterInfoAtIndex (size_t reg);
+
+ virtual size_t
+ GetRegisterSetCount ();
+
+ virtual const lldb_private::RegisterSet *
+ GetRegisterSet (size_t reg_set);
+
+ virtual bool
+ ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+ virtual bool
+ WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+ virtual bool
+ ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+ virtual bool
+ WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+ virtual uint32_t
+ ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+private:
+ //------------------------------------------------------------------
+ // For RegisterContextLLDB only
+ //------------------------------------------------------------------
+
+ lldb_private::RegisterSet m_reg_set0; // register set 0 (PC only)
+ lldb_private::RegisterInfo m_pc_reg_info;
+
+ lldb::addr_t m_pc_value;
+
+ DISALLOW_COPY_AND_ASSIGN (RegisterContextHistory);
+};
+} // namespace lldb_private
+
+#endif // lldb_RegisterContextHistory_h_
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index acb3154f6290..93641ede1bc7 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -363,71 +363,6 @@ enum {
NT_FREEBSD_PROCSTAT_AUXV = 16
};
-/// Note Structure found in ELF core dumps.
-/// This is PT_NOTE type program/segments in the core file.
-struct ELFNote
-{
- elf::elf_word n_namesz;
- elf::elf_word n_descsz;
- elf::elf_word n_type;
-
- std::string n_name;
-
- ELFNote() : n_namesz(0), n_descsz(0), n_type(0)
- {
- }
-
- /// Parse an ELFNote entry from the given DataExtractor starting at position
- /// \p offset.
- ///
- /// @param[in] data
- /// The DataExtractor to read from.
- ///
- /// @param[in,out] offset
- /// Pointer to an offset in the data. On return the offset will be
- /// advanced by the number of bytes read.
- ///
- /// @return
- /// True if the ELFRel entry was successfully read and false otherwise.
- bool
- Parse(const DataExtractor &data, lldb::offset_t *offset)
- {
- // Read all fields.
- if (data.GetU32(offset, &n_namesz, 3) == NULL)
- return false;
-
- // The name field is required to be nul-terminated, and n_namesz
- // includes the terminating nul in observed implementations (contrary
- // to the ELF-64 spec). A special case is needed for cores generated
- // by some older Linux versions, which write a note named "CORE"
- // without a nul terminator and n_namesz = 4.
- if (n_namesz == 4)
- {
- char buf[4];
- if (data.ExtractBytes (*offset, 4, data.GetByteOrder(), buf) != 4)
- return false;
- if (strncmp (buf, "CORE", 4) == 0)
- {
- n_name = "CORE";
- *offset += 4;
- return true;
- }
- }
-
- const char *cstr = data.GetCStr(offset, llvm::RoundUpToAlignment(n_namesz, 4));
- if (cstr == NULL)
- {
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
- if (log)
- log->Printf("Failed to parse note name lacking nul terminator");
-
- return false;
- }
- n_name = cstr;
- return true;
- }
-};
-
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void
ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 2ac7d20c6c60..2690992eeed3 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -65,6 +65,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
m_supports_p (eLazyBoolCalculate),
+ m_supports_QSaveRegisterState (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -110,17 +111,35 @@ GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient()
bool
GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
{
+ ResetDiscoverableSettings();
+
// Start the read thread after we send the handshake ack since if we
// fail to send the handshake ack, there is no reason to continue...
if (SendAck())
- return true;
-
- if (error_ptr)
- error_ptr->SetErrorString("failed to send the handshake ack");
+ {
+ // The return value from QueryNoAckModeSupported() is true if the packet
+ // was sent and _any_ response (including UNIMPLEMENTED) was received),
+ // or false if no response was received. This quickly tells us if we have
+ // a live connection to a remote GDB server...
+ if (QueryNoAckModeSupported())
+ {
+ return true;
+ }
+ else
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("failed to get reply to handshake packet");
+ }
+ }
+ else
+ {
+ if (error_ptr)
+ error_ptr->SetErrorString("failed to send the handshake ack");
+ }
return false;
}
-void
+bool
GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
{
if (m_supports_not_sending_acks == eLazyBoolCalculate)
@@ -136,8 +155,10 @@ GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
m_send_acks = false;
m_supports_not_sending_acks = eLazyBoolYes;
}
+ return true;
}
}
+ return false;
}
void
@@ -208,6 +229,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_vCont_s = eLazyBoolCalculate;
m_supports_vCont_S = eLazyBoolCalculate;
m_supports_p = eLazyBoolCalculate;
+ m_supports_QSaveRegisterState = eLazyBoolCalculate;
m_qHostInfo_is_valid = eLazyBoolCalculate;
m_qProcessInfo_is_valid = eLazyBoolCalculate;
m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
@@ -987,19 +1009,43 @@ GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str)
}
int
-GDBRemoteCommunicationClient::SendArgumentsPacket (char const *argv[])
-{
- if (argv && argv[0])
+GDBRemoteCommunicationClient::SendArgumentsPacket (const ProcessLaunchInfo &launch_info)
+{
+ // Since we don't get the send argv0 separate from the executable path, we need to
+ // make sure to use the actual exectuable path found in the launch_info...
+ std::vector<const char *> argv;
+ FileSpec exe_file = launch_info.GetExecutableFile();
+ std::string exe_path;
+ const char *arg = NULL;
+ const Args &launch_args = launch_info.GetArguments();
+ if (exe_file)
+ exe_path = exe_file.GetPath();
+ else
+ {
+ arg = launch_args.GetArgumentAtIndex(0);
+ if (arg)
+ exe_path = arg;
+ }
+ if (!exe_path.empty())
+ {
+ argv.push_back(exe_path.c_str());
+ for (uint32_t i=1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL; ++i)
+ {
+ if (arg)
+ argv.push_back(arg);
+ }
+ }
+ if (!argv.empty())
{
StreamString packet;
packet.PutChar('A');
- const char *arg;
- for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
+ for (size_t i = 0, n = argv.size(); i < n; ++i)
{
+ arg = argv[i];
const int arg_len = strlen(arg);
if (i > 0)
packet.PutChar(',');
- packet.Printf("%i,%i,", arg_len * 2, i);
+ packet.Printf("%i,%i,", arg_len * 2, (int)i);
packet.PutBytesAsRawHex8 (arg, arg_len);
}
@@ -1783,6 +1829,22 @@ GDBRemoteCommunicationClient::SetSTDERR (char const *path)
return -1;
}
+bool
+GDBRemoteCommunicationClient::GetWorkingDir (std::string &cwd)
+{
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse ("qGetWorkingDir", response, false))
+ {
+ if (response.IsUnsupportedResponse())
+ return false;
+ if (response.IsErrorResponse())
+ return false;
+ response.GetHexByteString (cwd);
+ return !cwd.empty();
+ }
+ return false;
+}
+
int
GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
{
@@ -2244,7 +2306,7 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
pid = LLDB_INVALID_PROCESS_ID;
StringExtractorGDBRemote response;
StreamString stream;
- stream.PutCString("qLaunchGDBServer:port:0;");
+ stream.PutCString("qLaunchGDBServer;");
std::string hostname;
if (Host::GetHostname (hostname))
{
@@ -2495,7 +2557,7 @@ GDBRemoteCommunicationClient::RunShellCommand (const char *command, //
uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
{
lldb_private::StreamString stream;
- stream.PutCString("qPlatform_RunCommand:");
+ stream.PutCString("qPlatform_shell:");
stream.PutBytesAsRawHex8(command, strlen(command));
stream.PutChar(',');
stream.PutHex32(timeout_sec);
@@ -2534,24 +2596,44 @@ GDBRemoteCommunicationClient::RunShellCommand (const char *command, //
return Error("unable to send packet");
}
-uint32_t
-GDBRemoteCommunicationClient::MakeDirectory (const std::string &path,
- mode_t mode)
+Error
+GDBRemoteCommunicationClient::MakeDirectory (const char *path,
+ uint32_t file_permissions)
{
lldb_private::StreamString stream;
- stream.PutCString("qPlatform_IO_MkDir:");
- stream.PutHex32(mode);
+ stream.PutCString("qPlatform_mkdir:");
+ stream.PutHex32(file_permissions);
stream.PutChar(',');
- stream.PutBytesAsRawHex8(path.c_str(), path.size());
+ stream.PutBytesAsRawHex8(path, strlen(path));
const char *packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
{
- return response.GetHexMaxU32(false, UINT32_MAX);
+ return Error(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
}
- return UINT32_MAX;
+ return Error();
+
+}
+Error
+GDBRemoteCommunicationClient::SetFilePermissions (const char *path,
+ uint32_t file_permissions)
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_chmod:");
+ stream.PutHex32(file_permissions);
+ stream.PutChar(',');
+ stream.PutBytesAsRawHex8(path, strlen(path));
+ const char *packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ return Error(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
+ }
+ return Error();
+
}
static uint64_t
@@ -2641,13 +2723,13 @@ GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_sp
return UINT64_MAX;
}
-uint32_t
-GDBRemoteCommunicationClient::GetFilePermissions(const lldb_private::FileSpec& file_spec, Error &error)
+Error
+GDBRemoteCommunicationClient::GetFilePermissions(const char *path, uint32_t &file_permissions)
{
+ Error error;
lldb_private::StreamString stream;
stream.PutCString("vFile:mode:");
- std::string path (file_spec.GetPath());
- stream.PutCStringAsRawHex8(path.c_str());
+ stream.PutCStringAsRawHex8(path);
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
@@ -2656,29 +2738,34 @@ GDBRemoteCommunicationClient::GetFilePermissions(const lldb_private::FileSpec& f
if (response.GetChar() != 'F')
{
error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet);
- return 0;
}
- const uint32_t mode = response.GetS32(-1);
- if (mode == -1)
+ else
{
- if (response.GetChar() == ',')
+ const uint32_t mode = response.GetS32(-1);
+ if (mode == -1)
{
- int response_errno = response.GetS32(-1);
- if (response_errno > 0)
- error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ else
+ error.SetErrorToGenericError();
+ }
else
error.SetErrorToGenericError();
}
+ else
+ {
+ file_permissions = mode & (S_IRWXU|S_IRWXG|S_IRWXO);
+ }
}
- else
- error.Clear();
- return mode & (S_IRWXU|S_IRWXG|S_IRWXO);
}
else
{
error.SetErrorStringWithFormat ("failed to send '%s' packet", packet);
}
- return 0;
+ return error;
}
uint64_t
@@ -2760,6 +2847,90 @@ GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
return 0;
}
+Error
+GDBRemoteCommunicationClient::CreateSymlink (const char *src, const char *dst)
+{
+ Error error;
+ lldb_private::StreamGDBRemote stream;
+ stream.PutCString("vFile:symlink:");
+ // the unix symlink() command reverses its parameters where the dst if first,
+ // so we follow suit here
+ stream.PutCStringAsRawHex8(dst);
+ stream.PutChar(',');
+ stream.PutCStringAsRawHex8(src);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() == 'F')
+ {
+ uint32_t result = response.GetU32(UINT32_MAX);
+ if (result != 0)
+ {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ }
+ }
+ else
+ {
+ // Should have returned with 'F<result>[,<errno>]'
+ error.SetErrorStringWithFormat("symlink failed");
+ }
+ }
+ else
+ {
+ error.SetErrorString ("failed to send vFile:symlink packet");
+ }
+ return error;
+}
+
+Error
+GDBRemoteCommunicationClient::Unlink (const char *path)
+{
+ Error error;
+ lldb_private::StreamGDBRemote stream;
+ stream.PutCString("vFile:unlink:");
+ // the unix symlink() command reverses its parameters where the dst if first,
+ // so we follow suit here
+ stream.PutCStringAsRawHex8(path);
+ const char* packet = stream.GetData();
+ int packet_len = stream.GetSize();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.GetChar() == 'F')
+ {
+ uint32_t result = response.GetU32(UINT32_MAX);
+ if (result != 0)
+ {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',')
+ {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ }
+ }
+ else
+ {
+ // Should have returned with 'F<result>[,<errno>]'
+ error.SetErrorStringWithFormat("unlink failed");
+ }
+ }
+ else
+ {
+ error.SetErrorString ("failed to send vFile:unlink packet");
+ }
+ return error;
+}
+
// Extension of host I/O packets to get whether a file exists.
bool
GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_spec)
@@ -2809,3 +2980,134 @@ GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_s
}
return false;
}
+
+bool
+GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg, StringExtractorGDBRemote &response)
+{
+ Mutex::Locker locker;
+ if (GetSequenceMutex (locker, "Didn't get sequence mutex for p packet."))
+ {
+ const bool thread_suffix_supported = GetThreadSuffixSupported();
+
+ if (thread_suffix_supported || SetCurrentThread(tid))
+ {
+ char packet[64];
+ int packet_len = 0;
+ if (thread_suffix_supported)
+ packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, tid);
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
+ assert (packet_len < ((int)sizeof(packet) - 1));
+ return SendPacketAndWaitForResponse(packet, response, false);
+ }
+ }
+ return false;
+
+}
+
+
+bool
+GDBRemoteCommunicationClient::ReadAllRegisters (lldb::tid_t tid, StringExtractorGDBRemote &response)
+{
+ Mutex::Locker locker;
+ if (GetSequenceMutex (locker, "Didn't get sequence mutex for g packet."))
+ {
+ const bool thread_suffix_supported = GetThreadSuffixSupported();
+
+ if (thread_suffix_supported || SetCurrentThread(tid))
+ {
+ char packet[64];
+ int packet_len = 0;
+ // Get all registers in one packet
+ if (thread_suffix_supported)
+ packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", tid);
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "g");
+ assert (packet_len < ((int)sizeof(packet) - 1));
+ return SendPacketAndWaitForResponse(packet, response, false);
+ }
+ }
+ return false;
+}
+bool
+GDBRemoteCommunicationClient::SaveRegisterState (lldb::tid_t tid, uint32_t &save_id)
+{
+ save_id = 0; // Set to invalid save ID
+ if (m_supports_QSaveRegisterState == eLazyBoolNo)
+ return false;
+
+ m_supports_QSaveRegisterState = eLazyBoolYes;
+ Mutex::Locker locker;
+ if (GetSequenceMutex (locker, "Didn't get sequence mutex for QSaveRegisterState."))
+ {
+ const bool thread_suffix_supported = GetThreadSuffixSupported();
+ if (thread_suffix_supported || SetCurrentThread(tid))
+ {
+ char packet[256];
+ if (thread_suffix_supported)
+ ::snprintf (packet, sizeof(packet), "QSaveRegisterState;thread:%4.4" PRIx64 ";", tid);
+ else
+ ::strncpy (packet, "QSaveRegisterState", sizeof(packet));
+
+ StringExtractorGDBRemote response;
+
+ if (SendPacketAndWaitForResponse(packet, response, false))
+ {
+ if (response.IsUnsupportedResponse())
+ {
+ // This packet isn't supported, don't try calling it again
+ m_supports_QSaveRegisterState = eLazyBoolNo;
+ }
+
+ const uint32_t response_save_id = response.GetU32(0);
+ if (response_save_id != 0)
+ {
+ save_id = response_save_id;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::RestoreRegisterState (lldb::tid_t tid, uint32_t save_id)
+{
+ // We use the "m_supports_QSaveRegisterState" variable here becuase the
+ // QSaveRegisterState and QRestoreRegisterState packets must both be supported in
+ // order to be useful
+ if (m_supports_QSaveRegisterState == eLazyBoolNo)
+ return false;
+
+ Mutex::Locker locker;
+ if (GetSequenceMutex (locker, "Didn't get sequence mutex for QRestoreRegisterState."))
+ {
+ const bool thread_suffix_supported = GetThreadSuffixSupported();
+ if (thread_suffix_supported || SetCurrentThread(tid))
+ {
+ char packet[256];
+ if (thread_suffix_supported)
+ ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u;thread:%4.4" PRIx64 ";", save_id, tid);
+ else
+ ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u" PRIx64 ";", save_id);
+
+ StringExtractorGDBRemote response;
+
+ if (SendPacketAndWaitForResponse(packet, response, false))
+ {
+ if (response.IsOKResponse())
+ {
+ return true;
+ }
+ else if (response.IsUnsupportedResponse())
+ {
+ // This packet isn't supported, don't try calling this packet or
+ // QSaveRegisterState again...
+ m_supports_QSaveRegisterState = eLazyBoolNo;
+ }
+ }
+ }
+ }
+ return false;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index d5535bbb1df3..564afbb2911c 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -38,7 +38,6 @@ public:
//------------------------------------------------------------------
GDBRemoteCommunicationClient(bool is_platform);
- virtual
~GDBRemoteCommunicationClient();
//------------------------------------------------------------------
@@ -65,10 +64,16 @@ public:
size_t packet_length,
StringExtractorGDBRemote &response);
- virtual bool
+ bool
GetThreadSuffixSupported ();
- void
+ // This packet is usually sent first and the boolean return value
+ // indicates if the packet was send and any response was received
+ // even in the response is UNIMPLEMENTED. If the packet failed to
+ // get a response, then false is returned. This quickly tells us
+ // if we were able to connect and communicte with the remote GDB
+ // server
+ bool
QueryNoAckModeSupported ();
void
@@ -109,7 +114,7 @@ public:
/// response was received.
//------------------------------------------------------------------
int
- SendArgumentsPacket (char const *argv[]);
+ SendArgumentsPacket (const lldb_private::ProcessLaunchInfo &launch_info);
//------------------------------------------------------------------
/// Sends a "QEnvironment:NAME=VALUE" packet that will build up the
@@ -185,7 +190,10 @@ public:
//------------------------------------------------------------------
/// Sets the working directory to \a path for a process that will
- /// be launched with the 'A' packet.
+ /// be launched with the 'A' packet for non platform based
+ /// connections. If this packet is sent to a GDB server that
+ /// implements the platform, it will change the current working
+ /// directory for the platform process.
///
/// @param[in] path
/// The path to a directory to use when launching our processs
@@ -196,6 +204,19 @@ public:
int
SetWorkingDir (char const *path);
+ //------------------------------------------------------------------
+ /// Gets the current working directory of a remote platform GDB
+ /// server.
+ ///
+ /// @param[out] cwd
+ /// The current working directory on the remote platform.
+ ///
+ /// @return
+ /// Boolean for success
+ //------------------------------------------------------------------
+ bool
+ GetWorkingDir (std::string &cwd);
+
lldb::addr_t
AllocateMemory (size_t size, uint32_t permissions);
@@ -356,45 +377,54 @@ public:
return m_interrupt_sent;
}
- virtual lldb::user_id_t
+ lldb::user_id_t
OpenFile (const lldb_private::FileSpec& file_spec,
uint32_t flags,
mode_t mode,
lldb_private::Error &error);
- virtual bool
+ bool
CloseFile (lldb::user_id_t fd,
lldb_private::Error &error);
- virtual lldb::user_id_t
+ lldb::user_id_t
GetFileSize (const lldb_private::FileSpec& file_spec);
- virtual uint32_t
- GetFilePermissions(const lldb_private::FileSpec& file_spec,
- lldb_private::Error &error);
+ lldb_private::Error
+ GetFilePermissions(const char *path, uint32_t &file_permissions);
+
+ lldb_private::Error
+ SetFilePermissions(const char *path, uint32_t file_permissions);
- virtual uint64_t
+ uint64_t
ReadFile (lldb::user_id_t fd,
uint64_t offset,
void *dst,
uint64_t dst_len,
lldb_private::Error &error);
- virtual uint64_t
+ uint64_t
WriteFile (lldb::user_id_t fd,
uint64_t offset,
const void* src,
uint64_t src_len,
lldb_private::Error &error);
- virtual uint32_t
- MakeDirectory (const std::string &path,
- mode_t mode);
+ lldb_private::Error
+ CreateSymlink (const char *src,
+ const char *dst);
- virtual bool
+ lldb_private::Error
+ Unlink (const char *path);
+
+ lldb_private::Error
+ MakeDirectory (const char *path,
+ uint32_t mode);
+
+ bool
GetFileExists (const lldb_private::FileSpec& file_spec);
- virtual lldb_private::Error
+ lldb_private::Error
RunShellCommand (const char *command, // Shouldn't be NULL
const char *working_dir, // Pass NULL to use the current working directory
int *status_ptr, // Pass NULL if you don't want the process exit status
@@ -402,7 +432,7 @@ public:
std::string *command_output, // Pass NULL if you don't want the command output
uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
- virtual bool
+ bool
CalculateMD5 (const lldb_private::FileSpec& file_spec,
uint64_t &high,
uint64_t &low);
@@ -411,6 +441,21 @@ public:
HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
StringExtractorGDBRemote &inputStringExtractor);
+ bool
+ ReadRegister(lldb::tid_t tid,
+ uint32_t reg_num,
+ StringExtractorGDBRemote &response);
+
+ bool
+ ReadAllRegisters (lldb::tid_t tid,
+ StringExtractorGDBRemote &response);
+
+ bool
+ SaveRegisterState (lldb::tid_t tid, uint32_t &save_id);
+
+ bool
+ RestoreRegisterState (lldb::tid_t tid, uint32_t save_id);
+
protected:
bool
@@ -438,6 +483,7 @@ protected:
lldb_private::LazyBool m_attach_or_wait_reply;
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
lldb_private::LazyBool m_supports_p;
+ lldb_private::LazyBool m_supports_QSaveRegisterState;
bool
m_supports_qProcessInfoPID:1,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index df036cdcc8e0..7cc3a05304d4 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -47,27 +47,9 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
m_proc_infos (),
m_proc_infos_index (0),
- m_lo_port_num (0),
- m_hi_port_num (0),
- m_next_port (0),
- m_use_port_range (false)
+ m_port_map (),
+ m_port_offset(0)
{
- // We seldom need to override the port number that the debugserver process
- // starts with. We just pass in 0 to let the system choose a random port.
- // In rare situation where the need arises, use two environment variables
- // to override.
- uint16_t lo_port_num = 0;
- uint16_t hi_port_num = 0;
- const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT");
- if (lo_port_c_str)
- lo_port_num = ::atoi(lo_port_c_str);
- const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT");
- if (hi_port_c_str)
- hi_port_num = ::atoi(hi_port_c_str);
- if (lo_port_num && hi_port_num && lo_port_num < hi_port_num)
- {
- SetPortRange(lo_port_num, hi_port_num);
- }
}
//----------------------------------------------------------------------
@@ -166,6 +148,9 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_qUserName:
return Handle_qUserName (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir:
+ return Handle_qGetWorkingDir(packet);
+
case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
return Handle_QEnvironment (packet);
@@ -190,38 +175,47 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
return Handle_QStartNoAckMode (packet);
- case StringExtractorGDBRemote::eServerPacketType_qPlatform_IO_MkDir:
- return Handle_qPlatform_IO_MkDir (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir:
+ return Handle_qPlatform_mkdir (packet);
- case StringExtractorGDBRemote::eServerPacketType_qPlatform_RunCommand:
- return Handle_qPlatform_RunCommand (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod:
+ return Handle_qPlatform_chmod (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_Open:
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell:
+ return Handle_qPlatform_shell (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_open:
return Handle_vFile_Open (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_Close:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_close:
return Handle_vFile_Close (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_pRead:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pread:
return Handle_vFile_pRead (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_pWrite:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite:
return Handle_vFile_pWrite (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_Size:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_size:
return Handle_vFile_Size (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_Mode:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_mode:
return Handle_vFile_Mode (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_Exists:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_exists:
return Handle_vFile_Exists (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_Stat:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_stat:
return Handle_vFile_Stat (packet);
- case StringExtractorGDBRemote::eServerPacketType_vFile_MD5:
+ case StringExtractorGDBRemote::eServerPacketType_vFile_md5:
return Handle_vFile_MD5 (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_symlink:
+ return Handle_vFile_symlink (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_unlink:
+ return Handle_vFile_unlink (packet);
}
return true;
}
@@ -329,12 +323,33 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
+#if defined(__APPLE__)
+
+#if defined(__arm__)
+ // For iOS devices, we are connected through a USB Mux so we never pretend
+ // to actually have a hostname as far as the remote lldb that is connecting
+ // to this lldb-platform is concerned
+ response.PutCString ("hostname:");
+ response.PutCStringAsRawHex8("localhost");
+ response.PutChar(';');
+#else // #if defined(__arm__)
+ if (Host::GetHostname (s))
+ {
+ response.PutCString ("hostname:");
+ response.PutCStringAsRawHex8(s.c_str());
+ response.PutChar(';');
+ }
+
+#endif // #if defined(__arm__)
+
+#else // #if defined(__APPLE__)
if (Host::GetHostname (s))
{
response.PutCString ("hostname:");
response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
}
+#endif // #if defined(__APPLE__)
return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
}
@@ -731,6 +746,7 @@ bool
GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid)
{
Mutex::Locker locker (m_spawned_pids_mutex);
+ FreePortForProcess(pid);
return m_spawned_pids.erase(pid) > 0;
}
bool
@@ -764,105 +780,119 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
std::string hostname;
// TODO: /tmp/ should not be hardcoded. User might want to override /tmp
// with the TMPDIR environnement variable
- char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
- if (::mkstemp (unix_socket_name) == -1)
+ packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
+ std::string name;
+ std::string value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value))
{
- error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno));
+ if (name.compare ("host") == 0)
+ hostname.swap(value);
+ else if (name.compare ("port") == 0)
+ port = Args::StringToUInt32(value.c_str(), 0, 0);
}
- else
- {
- packet.SetFilePos(::strlen ("qLaunchGDBServer:"));
- std::string name;
- std::string value;
- uint16_t port = UINT16_MAX;
- while (packet.GetNameColonValue(name, value))
- {
- if (name.compare ("host") == 0)
- hostname.swap(value);
- else if (name.compare ("port") == 0)
- port = Args::StringToUInt32(value.c_str(), 0, 0);
- }
- if (port == UINT16_MAX)
- port = GetAndUpdateNextPort();
+ if (port == UINT16_MAX)
+ port = GetNextAvailablePort();
- ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
- // Spawn a new thread to accept the port that gets bound after
- // binding to port 0 (zero).
- lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
+ // Spawn a new thread to accept the port that gets bound after
+ // binding to port 0 (zero).
+ lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
+ const char *unix_socket_name = NULL;
+ char unix_socket_name_buf[PATH_MAX] = "/tmp/XXXXXXXXX";
- if (port == 0)
+ if (port == 0)
+ {
+ if (::mkstemp (unix_socket_name_buf) == 0)
{
+ unix_socket_name = unix_socket_name_buf;
+ ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
accept_thread = Host::ThreadCreate (unix_socket_name,
AcceptPortFromInferior,
connect_url,
&error);
}
+ else
+ {
+ error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno));
+ }
+ }
- if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
+ if (error.Success())
+ {
+ // Spawn a debugserver and try to get the port it listens to.
+ ProcessLaunchInfo debugserver_launch_info;
+ StreamString host_and_port;
+ if (hostname.empty())
+ hostname = "localhost";
+ host_and_port.Printf("%s:%u", hostname.c_str(), port);
+ const char *host_and_port_cstr = host_and_port.GetString().c_str();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
+
+ debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
+
+ error = StartDebugserverProcess (host_and_port_cstr,
+ unix_socket_name,
+ debugserver_launch_info);
+
+ lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+
+
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
- // Spawn a debugserver and try to get the port it listens to.
- ProcessLaunchInfo debugserver_launch_info;
- StreamString host_and_port;
- if (hostname.empty())
- hostname = "localhost";
- host_and_port.Printf("%s:%u", hostname.c_str(), port);
- const char *host_and_port_cstr = host_and_port.GetString().c_str();
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
- error = StartDebugserverProcess (host_and_port_cstr,
- unix_socket_name,
- debugserver_launch_info);
-
- lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
-
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- {
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- m_spawned_pids.insert(debugserver_pid);
- }
- Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false);
- }
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(debugserver_pid);
+ if (port > 0)
+ AssociatePortWithProcess(port, debugserver_pid);
+ }
+ else
+ {
+ if (port > 0)
+ FreePort (port);
+ }
- if (error.Success())
- {
- bool success = false;
+ if (error.Success())
+ {
+ bool success = false;
- if (accept_thread)
+ if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
+ {
+ thread_result_t accept_thread_result = NULL;
+ if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
{
- thread_result_t accept_thread_result = NULL;
- if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+ if (accept_thread_result)
{
- if (accept_thread_result)
- {
- port = (intptr_t)accept_thread_result;
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
- assert (response_len < sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
- }
+ port = (intptr_t)accept_thread_result;
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
}
}
- else
- {
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
- assert (response_len < sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
+ }
+ else
+ {
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacketNoLock (response, response_len) > 0;
- }
- ::unlink (unix_socket_name);
+ }
+ Host::Unlink (unix_socket_name);
- if (!success)
- {
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- ::kill (debugserver_pid, SIGINT);
- }
- return success;
+ if (!success)
+ {
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ ::kill (debugserver_pid, SIGINT);
}
+ return success;
+ }
+ else if (accept_thread)
+ {
+ Host::Unlink (unix_socket_name);
}
}
}
@@ -896,7 +926,7 @@ GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemo
{
Mutex::Locker locker (m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
+ return SendOKResponse();
}
usleep (10000);
}
@@ -905,7 +935,7 @@ GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemo
{
Mutex::Locker locker (m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
+ return SendOKResponse();
}
Host::Kill (pid, SIGKILL);
@@ -915,12 +945,12 @@ GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemo
{
Mutex::Locker locker (m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
+ return SendOKResponse();
}
usleep (10000);
}
}
- return SendErrorResponse (10);
+ return SendErrorResponse (11);
}
bool
@@ -944,7 +974,7 @@ GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &pa
m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
return SendOKResponse ();
}
- return SendErrorResponse (11);
+ return SendErrorResponse (12);
}
bool
@@ -959,7 +989,7 @@ GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &pack
m_process_launch_info.SetArchitecture(arch_spec);
return SendOKResponse();
}
- return SendErrorResponse(12);
+ return SendErrorResponse(13);
}
bool
@@ -979,11 +1009,61 @@ GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &p
packet.SetFilePos(::strlen ("QSetWorkingDir:"));
std::string path;
packet.GetHexByteString(path);
- m_process_launch_info.SwapWorkingDirectory (path);
+ if (m_is_platform)
+ {
+#ifdef _WIN32
+ // Not implemented on Windows
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_QSetWorkingDir unimplemented");
+#else
+ // If this packet is sent to a platform, then change the current working directory
+ if (::chdir(path.c_str()) != 0)
+ return SendErrorResponse(errno);
+#endif
+ }
+ else
+ {
+ m_process_launch_info.SwapWorkingDirectory (path);
+ }
return SendOKResponse ();
}
bool
+GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
+{
+ StreamString response;
+
+ if (m_is_platform)
+ {
+ // If this packet is sent to a platform, then change the current working directory
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, sizeof(cwd)) == NULL)
+ {
+ return SendErrorResponse(errno);
+ }
+ else
+ {
+ response.PutBytesAsRawHex8(cwd, strlen(cwd));
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+ }
+ }
+ else
+ {
+ const char *working_dir = m_process_launch_info.GetWorkingDirectory();
+ if (working_dir && working_dir[0])
+ {
+ response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
+ SendPacketNoLock(response.GetData(), response.GetSize());
+ return true;
+ }
+ else
+ {
+ return SendErrorResponse(14);
+ }
+ }
+}
+
+bool
GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetSTDIN:"));
@@ -997,7 +1077,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (13);
+ return SendErrorResponse (15);
}
bool
@@ -1014,7 +1094,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (14);
+ return SendErrorResponse (16);
}
bool
@@ -1031,7 +1111,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse ();
}
- return SendErrorResponse (15);
+ return SendErrorResponse (17);
}
bool
@@ -1044,19 +1124,40 @@ GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &
}
bool
-GDBRemoteCommunicationServer::Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet)
+GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
{
- packet.SetFilePos(::strlen("qPlatform_IO_MkDir:"));
+ packet.SetFilePos(::strlen("qPlatform_mkdir:"));
mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
- if (packet.GetChar() != ',')
- return false;
- std::string path;
- packet.GetHexByteString(path);
- uint32_t retcode = Host::MakeDirectory(path.c_str(),mode);
- StreamString response;
- response.PutHex32(retcode);
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ if (packet.GetChar() == ',')
+ {
+ std::string path;
+ packet.GetHexByteString(path);
+ Error error = Host::MakeDirectory(path.c_str(),mode);
+ if (error.Success())
+ return SendPacketNoLock ("OK", 2);
+ else
+ return SendErrorResponse(error.GetError());
+ }
+ return SendErrorResponse(20);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_chmod:"));
+
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() == ',')
+ {
+ std::string path;
+ packet.GetHexByteString(path);
+ Error error = Host::SetFilePermissions (path.c_str(), mode);
+ if (error.Success())
+ return SendPacketNoLock ("OK", 2);
+ else
+ return SendErrorResponse(error.GetError());
+ }
+ return SendErrorResponse(19);
}
bool
@@ -1065,24 +1166,28 @@ GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packe
packet.SetFilePos(::strlen("vFile:open:"));
std::string path;
packet.GetHexByteStringTerminatedBy(path,',');
- if (path.size() == 0)
- return false;
- if (packet.GetChar() != ',')
- return false;
- uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX);
- if (packet.GetChar() != ',')
- return false;
- mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
- Error error;
- int fd = ::open (path.c_str(), flags, mode);
- const int save_errno = fd == -1 ? errno : 0;
- StreamString response;
- response.PutChar('F');
- response.Printf("%i", fd);
- if (save_errno)
- response.Printf(",%i", save_errno);
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ if (!path.empty())
+ {
+ if (packet.GetChar() == ',')
+ {
+ uint32_t flags = packet.GetHexMaxU32(false, 0);
+ if (packet.GetChar() == ',')
+ {
+ mode_t mode = packet.GetHexMaxU32(false, 0600);
+ Error error;
+ int fd = ::open (path.c_str(), flags, mode);
+ printf ("open('%s', flags=0x%x, mode=%o) fd = %i (%s)\n", path.c_str(), flags, mode, fd, fd == -1 ? strerror(errno) : "<success>");
+ const int save_errno = fd == -1 ? errno : 0;
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", fd);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
+ }
+ }
+ return SendErrorResponse(18);
}
bool
@@ -1107,8 +1212,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &pack
response.Printf("%i", err);
if (save_errno)
response.Printf(",%i", save_errno);
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendPacketNoLock(response.GetData(), response.GetSize());
}
bool
@@ -1116,37 +1220,40 @@ GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &pack
{
#ifdef _WIN32
// Not implemented on Windows
- return false;
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pRead() unimplemented");
#else
StreamGDBRemote response;
packet.SetFilePos(::strlen("vFile:pread:"));
int fd = packet.GetS32(-1);
- if (packet.GetChar() != ',')
- return false;
- uint64_t count = packet.GetU64(UINT64_MAX);
- if (packet.GetChar() != ',')
- return false;
- uint64_t offset = packet.GetU64(UINT32_MAX);
- if (count == UINT64_MAX)
- {
- response.Printf("F-1:%i", EINVAL);
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
- }
- std::string buffer(count, 0);
- const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
- const int save_errno = bytes_read == -1 ? errno : 0;
- response.PutChar('F');
- response.Printf("%zi", bytes_read);
- if (save_errno)
- response.Printf(",%i", save_errno);
- else
+ if (packet.GetChar() == ',')
{
- response.PutChar(';');
- response.PutEscapedBytes(&buffer[0], bytes_read);
+ uint64_t count = packet.GetU64(UINT64_MAX);
+ if (packet.GetChar() == ',')
+ {
+ uint64_t offset = packet.GetU64(UINT32_MAX);
+ if (count == UINT64_MAX)
+ {
+ response.Printf("F-1:%i", EINVAL);
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
+
+ std::string buffer(count, 0);
+ const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
+ const int save_errno = bytes_read == -1 ? errno : 0;
+ response.PutChar('F');
+ response.Printf("%zi", bytes_read);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ else
+ {
+ response.PutChar(';');
+ response.PutEscapedBytes(&buffer[0], bytes_read);
+ }
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
}
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendErrorResponse(21);
+
#endif
}
@@ -1154,8 +1261,7 @@ bool
GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
{
#ifdef _WIN32
- // Not implemented on Windows
- return false;
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pWrite() unimplemented");
#else
packet.SetFilePos(::strlen("vFile:pwrite:"));
@@ -1163,27 +1269,28 @@ GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &pac
response.PutChar('F');
int fd = packet.GetU32(UINT32_MAX);
- if (packet.GetChar() != ',')
- return false;
- off_t offset = packet.GetU64(UINT32_MAX);
- if (packet.GetChar() != ',')
- return false;
- std::string buffer;
- if (packet.GetEscapedBinaryData(buffer))
- {
- const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
- const int save_errno = bytes_written == -1 ? errno : 0;
- response.Printf("%zi", bytes_written);
- if (save_errno)
- response.Printf(",%i", save_errno);
- }
- else
+ if (packet.GetChar() == ',')
{
- response.Printf ("-1,%i", EINVAL);
+ off_t offset = packet.GetU64(UINT32_MAX);
+ if (packet.GetChar() == ',')
+ {
+ std::string buffer;
+ if (packet.GetEscapedBinaryData(buffer))
+ {
+ const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
+ const int save_errno = bytes_written == -1 ? errno : 0;
+ response.Printf("%zi", bytes_written);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ }
+ else
+ {
+ response.Printf ("-1,%i", EINVAL);
+ }
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
}
-
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendErrorResponse(27);
#endif
}
@@ -1193,19 +1300,20 @@ GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packe
packet.SetFilePos(::strlen("vFile:size:"));
std::string path;
packet.GetHexByteString(path);
- if (path.empty())
- return false;
- lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
- StreamString response;
- response.PutChar('F');
- response.PutHex64(retcode);
- if (retcode == UINT64_MAX)
+ if (!path.empty())
{
- response.PutChar(',');
- response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutHex64(retcode);
+ if (retcode == UINT64_MAX)
+ {
+ response.PutChar(',');
+ response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
+ }
+ return SendPacketNoLock(response.GetData(), response.GetSize());
}
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendErrorResponse(22);
}
bool
@@ -1214,16 +1322,17 @@ GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packe
packet.SetFilePos(::strlen("vFile:mode:"));
std::string path;
packet.GetHexByteString(path);
- if (path.empty())
- return false;
- Error error;
- const uint32_t mode = File::GetPermissions(path.c_str(), error);
- StreamString response;
- response.Printf("F%u", mode);
- if (mode == 0 || error.Fail())
- response.Printf(",%i", (int)error.GetError());
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ if (!path.empty())
+ {
+ Error error;
+ const uint32_t mode = File::GetPermissions(path.c_str(), error);
+ StreamString response;
+ response.Printf("F%u", mode);
+ if (mode == 0 || error.Fail())
+ response.Printf(",%i", (int)error.GetError());
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
+ return SendErrorResponse(23);
}
bool
@@ -1232,87 +1341,118 @@ GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &pac
packet.SetFilePos(::strlen("vFile:exists:"));
std::string path;
packet.GetHexByteString(path);
- if (path.empty())
- return false;
- bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
+ if (!path.empty())
+ {
+ bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutChar(',');
+ if (retcode)
+ response.PutChar('1');
+ else
+ response.PutChar('0');
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
+ return SendErrorResponse(24);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("vFile:symlink:"));
+ std::string dst, src;
+ packet.GetHexByteStringTerminatedBy(dst, ',');
+ packet.GetChar(); // Skip ',' char
+ packet.GetHexByteString(src);
+ Error error = Host::Symlink(src.c_str(), dst.c_str());
StreamString response;
- response.PutChar('F');
- response.PutChar(',');
- if (retcode)
- response.PutChar('1');
- else
- response.PutChar('0');
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ response.Printf("F%u,%u", error.GetError(), error.GetError());
+ return SendPacketNoLock(response.GetData(), response.GetSize());
}
bool
-GDBRemoteCommunicationServer::Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet)
+GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
{
- packet.SetFilePos(::strlen("qPlatform_RunCommand:"));
+ packet.SetFilePos(::strlen("vFile:unlink:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ Error error = Host::Unlink(path.c_str());
+ StreamString response;
+ response.Printf("F%u,%u", error.GetError(), error.GetError());
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen("qPlatform_shell:"));
std::string path;
std::string working_dir;
packet.GetHexByteStringTerminatedBy(path,',');
- if (path.size() == 0)
- return false;
- if (packet.GetChar() != ',')
- return false;
- // FIXME: add timeout to qPlatform_RunCommand packet
- // uint32_t timeout = packet.GetHexMaxU32(false, 32);
- uint32_t timeout = 10;
- if (packet.GetChar() == ',')
- packet.GetHexByteString(working_dir);
- int status, signo;
- std::string output;
- Error err = Host::RunShellCommand(path.c_str(),
- working_dir.empty() ? NULL : working_dir.c_str(),
- &status, &signo, &output, timeout);
- StreamGDBRemote response;
- if (err.Fail())
+ if (!path.empty())
{
- response.PutCString("F,");
- response.PutHex32(UINT32_MAX);
- }
- else
- {
- response.PutCString("F,");
- response.PutHex32(status);
- response.PutChar(',');
- response.PutHex32(signo);
- response.PutChar(',');
- response.PutEscapedBytes(output.c_str(), output.size());
+ if (packet.GetChar() == ',')
+ {
+ // FIXME: add timeout to qPlatform_shell packet
+ // uint32_t timeout = packet.GetHexMaxU32(false, 32);
+ uint32_t timeout = 10;
+ if (packet.GetChar() == ',')
+ packet.GetHexByteString(working_dir);
+ int status, signo;
+ std::string output;
+ Error err = Host::RunShellCommand(path.c_str(),
+ working_dir.empty() ? NULL : working_dir.c_str(),
+ &status, &signo, &output, timeout);
+ StreamGDBRemote response;
+ if (err.Fail())
+ {
+ response.PutCString("F,");
+ response.PutHex32(UINT32_MAX);
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex32(status);
+ response.PutChar(',');
+ response.PutHex32(signo);
+ response.PutChar(',');
+ response.PutEscapedBytes(output.c_str(), output.size());
+ }
+ return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
}
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendErrorResponse(24);
}
bool
GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
{
- return false;
+ return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented");
}
bool
GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
{
- packet.SetFilePos(::strlen("vFile:exists:"));
+ packet.SetFilePos(::strlen("vFile:MD5:"));
std::string path;
packet.GetHexByteString(path);
- if (path.size() == 0)
- return false;
- uint64_t a,b;
- StreamGDBRemote response;
- if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
+ if (!path.empty())
{
- response.PutCString("F,");
- response.PutCString("x");
- }
- else
- {
- response.PutCString("F,");
- response.PutHex64(a);
- response.PutHex64(b);
+ uint64_t a,b;
+ StreamGDBRemote response;
+ if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false)
+ {
+ response.PutCString("F,");
+ response.PutCString("x");
+ }
+ else
+ {
+ response.PutCString("F,");
+ response.PutHex64(a);
+ response.PutHex64(b);
+ }
+ return SendPacketNoLock(response.GetData(), response.GetSize());
}
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendErrorResponse(25);
}
+
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 64f6f8de1a21..721ea5012b33 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -26,6 +26,8 @@ class StringExtractorGDBRemote;
class GDBRemoteCommunicationServer : public GDBRemoteCommunication
{
public:
+ typedef std::map<uint16_t, lldb::pid_t> PortMap;
+
enum
{
eBroadcastBitRunPacketSent = kLoUserBroadcastBit
@@ -58,30 +60,85 @@ public:
// Set both ports to zero to let the platform automatically bind to
// a port chosen by the OS.
void
- SetPortRange (uint16_t lo_port_num, uint16_t hi_port_num)
+ SetPortMap (PortMap &&port_map)
{
- m_lo_port_num = lo_port_num;
- m_hi_port_num = hi_port_num;
- m_next_port = m_lo_port_num;
- m_use_port_range = true;
+ m_port_map = port_map;
}
- // If we are using a port range, get and update the next port to be used variable.
- // Otherwise, just return 0.
+ //----------------------------------------------------------------------
+ // If we are using a port map where we can only use certain ports,
+ // get the next available port.
+ //
+ // If we are using a port map and we are out of ports, return UINT16_MAX
+ //
+ // If we aren't using a port map, return 0 to indicate we should bind to
+ // port 0 and then figure out which port we used.
+ //----------------------------------------------------------------------
uint16_t
- GetAndUpdateNextPort ()
+ GetNextAvailablePort ()
{
- if (!m_use_port_range)
- return 0;
- uint16_t val = m_next_port;
- if (++m_next_port > m_hi_port_num)
- m_next_port = m_lo_port_num;
- return val;
+ if (m_port_map.empty())
+ return 0; // Bind to port zero and get a port, we didn't have any limitations
+
+ for (auto &pair : m_port_map)
+ {
+ if (pair.second == LLDB_INVALID_PROCESS_ID)
+ {
+ pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
+ return pair.first;
+ }
+ }
+ return UINT16_MAX;
}
-protected:
- //typedef std::map<uint16_t, lldb::pid_t> PortToPIDMap;
+ bool
+ AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
+ {
+ PortMap::iterator pos = m_port_map.find(port);
+ if (pos != m_port_map.end())
+ {
+ pos->second = pid;
+ return true;
+ }
+ return false;
+ }
+
+ bool
+ FreePort (uint16_t port)
+ {
+ PortMap::iterator pos = m_port_map.find(port);
+ if (pos != m_port_map.end())
+ {
+ pos->second = LLDB_INVALID_PROCESS_ID;
+ return true;
+ }
+ return false;
+ }
+
+ bool
+ FreePortForProcess (lldb::pid_t pid)
+ {
+ if (!m_port_map.empty())
+ {
+ for (auto &pair : m_port_map)
+ {
+ if (pair.second == pid)
+ {
+ pair.second = LLDB_INVALID_PROCESS_ID;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ void
+ SetPortOffset (uint16_t port_offset)
+ {
+ m_port_offset = port_offset;
+ }
+
+protected:
lldb::thread_t m_async_thread;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
@@ -89,11 +146,8 @@ protected:
lldb_private::Mutex m_spawned_pids_mutex;
lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
- uint16_t m_lo_port_num;
- uint16_t m_hi_port_num;
- //PortToPIDMap m_port_to_pid_map;
- uint16_t m_next_port;
- bool m_use_port_range;
+ PortMap m_port_map;
+ uint16_t m_port_offset;
size_t
@@ -121,7 +175,10 @@ protected:
Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
bool
- Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet);
+ Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qPlatform_chmod (StringExtractorGDBRemote &packet);
bool
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
@@ -155,6 +212,9 @@ protected:
bool
Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qGetWorkingDir (StringExtractorGDBRemote &packet);
bool
Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
@@ -188,6 +248,12 @@ protected:
bool
Handle_vFile_Exists (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_symlink (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_vFile_unlink (StringExtractorGDBRemote &packet);
bool
Handle_vFile_Stat (StringExtractorGDBRemote &packet);
@@ -196,7 +262,7 @@ protected:
Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
bool
- Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet);
+ Handle_qPlatform_shell (StringExtractorGDBRemote &packet);
private:
bool
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index c4e468f89f35..c291df786d10 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -153,20 +153,13 @@ bool
GDBRemoteRegisterContext::GetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
GDBRemoteCommunicationClient &gdb_comm)
{
- char packet[64];
- StringExtractorGDBRemote response;
- int packet_len = 0;
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- if (gdb_comm.GetThreadSuffixSupported())
- packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, m_thread.GetProtocolID());
- else
- packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
- assert (packet_len < ((int)sizeof(packet) - 1));
- if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
+ StringExtractorGDBRemote response;
+ if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), reg, response))
return PrivateSetRegisterValue (reg, response);
-
return false;
}
+
bool
GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data)
{
@@ -185,93 +178,51 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE
if (!GetRegisterIsValid(reg))
{
- Mutex::Locker locker;
- if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read register."))
+ if (m_read_all_at_once)
{
- const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
+ StringExtractorGDBRemote response;
+ if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))
+ return false;
+ if (response.IsNormalResponse())
+ if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
+ SetAllRegisterValid (true);
+ }
+ else if (reg_info->value_regs)
+ {
+ // Process this composite register request by delegating to the constituent
+ // primordial registers.
+
+ // Index of the primordial register.
+ bool success = true;
+ for (uint32_t idx = 0; success; ++idx)
{
- char packet[64];
- StringExtractorGDBRemote response;
- int packet_len = 0;
- if (m_read_all_at_once)
- {
- // Get all registers in one packet
- if (thread_suffix_supported)
- packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
- else
- packet_len = ::snprintf (packet, sizeof(packet), "g");
- assert (packet_len < ((int)sizeof(packet) - 1));
- if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
- {
- if (response.IsNormalResponse())
- if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
- SetAllRegisterValid (true);
- }
- }
- else if (reg_info->value_regs)
- {
- // Process this composite register request by delegating to the constituent
- // primordial registers.
-
- // Index of the primordial register.
- bool success = true;
- for (uint32_t idx = 0; success; ++idx)
- {
- const uint32_t prim_reg = reg_info->value_regs[idx];
- if (prim_reg == LLDB_INVALID_REGNUM)
- break;
- // We have a valid primordial regsiter as our constituent.
- // Grab the corresponding register info.
- const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
- if (prim_reg_info == NULL)
- success = false;
- else
- {
- // Read the containing register if it hasn't already been read
- if (!GetRegisterIsValid(prim_reg))
- success = GetPrimordialRegister(prim_reg_info, gdb_comm);
- }
- }
-
- if (success)
- {
- // If we reach this point, all primordial register requests have succeeded.
- // Validate this composite register.
- SetRegisterIsValid (reg_info, true);
- }
- }
+ const uint32_t prim_reg = reg_info->value_regs[idx];
+ if (prim_reg == LLDB_INVALID_REGNUM)
+ break;
+ // We have a valid primordial regsiter as our constituent.
+ // Grab the corresponding register info.
+ const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
+ if (prim_reg_info == NULL)
+ success = false;
else
{
- // Get each register individually
- GetPrimordialRegister(reg_info, gdb_comm);
+ // Read the containing register if it hasn't already been read
+ if (!GetRegisterIsValid(prim_reg))
+ success = GetPrimordialRegister(prim_reg_info, gdb_comm);
}
}
+
+ if (success)
+ {
+ // If we reach this point, all primordial register requests have succeeded.
+ // Validate this composite register.
+ SetRegisterIsValid (reg_info, true);
+ }
}
else
{
-#if LLDB_CONFIGURATION_DEBUG
- StreamString strm;
- gdb_comm.DumpHistory(strm);
- Host::SetCrashDescription (strm.GetData());
- assert (!"Didn't get sequence mutex for read register.");
-#else
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
- if (log)
- {
- if (log->GetVerbose())
- {
- StreamString strm;
- gdb_comm.DumpHistory(strm);
- log->Printf("error: failed to get packet sequence mutex, not sending read register for \"%s\":\n%s", reg_info->name, strm.GetData());
- }
- else
- {
- log->Printf("error: failed to get packet sequence mutex, not sending read register for \"%s\"", reg_info->name);
- }
- }
-#endif
+ // Get each register individually
+ GetPrimordialRegister(reg_info, gdb_comm);
}
// Make sure we got a valid register value after reading it
@@ -488,6 +439,54 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *
return false;
}
+bool
+GDBRemoteRegisterContext::ReadAllRegisterValues (lldb_private::RegisterCheckpoint &reg_checkpoint)
+{
+ ExecutionContext exe_ctx (CalculateThread());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (process == NULL || thread == NULL)
+ return false;
+
+ GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+
+ uint32_t save_id = 0;
+ if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id))
+ {
+ reg_checkpoint.SetID(save_id);
+ reg_checkpoint.GetData().reset();
+ return true;
+ }
+ else
+ {
+ reg_checkpoint.SetID(0); // Invalid save ID is zero
+ return ReadAllRegisterValues(reg_checkpoint.GetData());
+ }
+}
+
+bool
+GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb_private::RegisterCheckpoint &reg_checkpoint)
+{
+ uint32_t save_id = reg_checkpoint.GetID();
+ if (save_id != 0)
+ {
+ ExecutionContext exe_ctx (CalculateThread());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (process == NULL || thread == NULL)
+ return false;
+
+ GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+
+ return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id);
+ }
+ else
+ {
+ return WriteAllRegisterValues(reg_checkpoint.GetData());
+ }
+}
bool
GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 7a49d693d44e..38f29bbca0de 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -91,6 +91,12 @@ public:
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+ virtual bool
+ ReadAllRegisterValues (lldb_private::RegisterCheckpoint &reg_checkpoint);
+
+ virtual bool
+ WriteAllRegisterValues (const lldb_private::RegisterCheckpoint &reg_checkpoint);
+
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index aff9c7bc977c..7f1fbefc1b7e 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -820,7 +820,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_
}
const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (10);
- int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info.GetArguments().GetConstArgumentVector());
+ int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info);
if (arg_packet_err == 0)
{
std::string error_str;
@@ -926,15 +926,13 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
// then we aren't actually connected to anything, so try and do the
// handshake with the remote GDB server and make sure that goes
// alright.
- if (!m_gdb_comm.HandshakeWithServer (NULL))
+ if (!m_gdb_comm.HandshakeWithServer (&error))
{
m_gdb_comm.Disconnect();
if (error.Success())
error.SetErrorString("not connected to remote gdb server");
return error;
}
- m_gdb_comm.ResetDiscoverableSettings();
- m_gdb_comm.QueryNoAckModeSupported ();
m_gdb_comm.GetThreadSuffixSupported ();
m_gdb_comm.GetListThreadsInStopReplySupported ();
m_gdb_comm.GetHostInfo ();
@@ -1158,6 +1156,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
}
+bool
+ProcessGDBRemote::SetExitStatus (int exit_status, const char *cstr)
+{
+ m_gdb_comm.Disconnect();
+ return Process::SetExitStatus (exit_status, cstr);
+}
+
void
ProcessGDBRemote::DidAttach ()
{
@@ -2787,6 +2792,7 @@ ProcessGDBRemote::MonitorDebugserverProcess
void
ProcessGDBRemote::KillDebugserverProcess ()
{
+ m_gdb_comm.Disconnect();
if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
{
Host::Kill (m_debugserver_pid, SIGINT);
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index b18ac5b1723e..35244074bab7 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -222,6 +222,13 @@ public:
{
return m_gdb_comm;
}
+
+ //----------------------------------------------------------------------
+ // Override SetExitStatus so we can disconnect from the remote GDB server
+ //----------------------------------------------------------------------
+ virtual bool
+ SetExitStatus (int exit_status, const char *cstr);
+
protected:
friend class ThreadGDBRemote;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index a4968c455a68..daa3b0aa6666 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -32,6 +32,7 @@ DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
dw_offset_t debug_ranges_offset = offset;
while (Extract(dwarf2Data, &offset, range_list))
{
+ range_list.Sort();
m_range_map[debug_ranges_offset] = range_list;
debug_ranges_offset = offset;
}
diff --git a/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp
index c089a7bb8db8..19edea4cb234 100644
--- a/source/Symbol/UnwindPlan.cpp
+++ b/source/Symbol/UnwindPlan.cpp
@@ -10,6 +10,7 @@
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
@@ -373,6 +374,25 @@ UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
bool
UnwindPlan::PlanValidAtAddress (Address addr)
{
+ // If this UnwindPlan has no rows, it is an invalid UnwindPlan.
+ if (GetRowCount() == 0)
+ {
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ if (log)
+ log->Printf ("Testing if UnwindPlan is valid at pc 0x%" PRIx64 ": No unwind rows - is invalid.");
+ return false;
+ }
+
+ // If the 0th Row of unwind instructions is missing, or if it doesn't provide
+ // a register to use to find the Canonical Frame Address, this is not a valid UnwindPlan.
+ if (GetRowAtIndex(0).get() == NULL || GetRowAtIndex(0)->GetCFARegister() == LLDB_INVALID_REGNUM)
+ {
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ if (log)
+ log->Printf ("Testing if UnwindPlan is valid at pc 0x%" PRIx64 ": No CFA register - is invalid.");
+ return false;
+ }
+
if (!m_plan_valid_address_range.GetBaseAddress().IsValid() || m_plan_valid_address_range.GetByteSize() == 0)
return true;
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index 75d94bd91ce3..66f9c0e552a8 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -237,6 +237,7 @@ Platform::Platform (bool is_host) :
m_system_arch_set_while_connected (false),
m_sdk_sysroot (),
m_sdk_build (),
+ m_working_dir (),
m_remote_url (),
m_name (),
m_major_os_version (UINT32_MAX),
@@ -319,6 +320,10 @@ Platform::GetStatus (Stream &strm)
strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");
}
+ if (GetWorkingDirectory())
+ {
+ strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString());
+ }
if (!IsConnected())
return;
@@ -405,12 +410,332 @@ Platform::GetOSKernelDescription (std::string &s)
}
ConstString
+Platform::GetWorkingDirectory ()
+{
+ if (IsHost())
+ {
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, sizeof(cwd)))
+ return ConstString(cwd);
+ else
+ return ConstString();
+ }
+ else
+ {
+ if (!m_working_dir)
+ m_working_dir = GetRemoteWorkingDirectory();
+ return m_working_dir;
+ }
+}
+
+
+struct RecurseCopyBaton
+{
+ const FileSpec& dst;
+ Platform *platform_ptr;
+ Error error;
+};
+
+
+static FileSpec::EnumerateDirectoryResult
+RecurseCopy_Callback (void *baton,
+ FileSpec::FileType file_type,
+ const FileSpec &src)
+{
+ RecurseCopyBaton* rc_baton = (RecurseCopyBaton*)baton;
+ switch (file_type)
+ {
+ case FileSpec::eFileTypePipe:
+ case FileSpec::eFileTypeSocket:
+ // we have no way to copy pipes and sockets - ignore them and continue
+ return FileSpec::eEnumerateDirectoryResultNext;
+ break;
+
+ case FileSpec::eFileTypeDirectory:
+ {
+ // make the new directory and get in there
+ FileSpec dst_dir = rc_baton->dst;
+ if (!dst_dir.GetFilename())
+ dst_dir.GetFilename() = src.GetLastPathComponent();
+ std::string dst_dir_path (dst_dir.GetPath());
+ Error error = rc_baton->platform_ptr->MakeDirectory(dst_dir_path.c_str(), lldb::eFilePermissionsDirectoryDefault);
+ if (error.Fail())
+ {
+ rc_baton->error.SetErrorStringWithFormat("unable to setup directory %s on remote end", dst_dir_path.c_str());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ }
+
+ // now recurse
+ std::string src_dir_path (src.GetPath());
+
+ // Make a filespec that only fills in the directory of a FileSpec so
+ // when we enumerate we can quickly fill in the filename for dst copies
+ FileSpec recurse_dst;
+ recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
+ RecurseCopyBaton rc_baton2 = { recurse_dst, rc_baton->platform_ptr, Error() };
+ FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &rc_baton2);
+ if (rc_baton2.error.Fail())
+ {
+ rc_baton->error.SetErrorString(rc_baton2.error.AsCString());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+ }
+ break;
+
+ case FileSpec::eFileTypeSymbolicLink:
+ {
+ // copy the file and keep going
+ FileSpec dst_file = rc_baton->dst;
+ if (!dst_file.GetFilename())
+ dst_file.GetFilename() = src.GetFilename();
+
+ char buf[PATH_MAX];
+
+ rc_baton->error = Host::Readlink (src.GetPath().c_str(), buf, sizeof(buf));
+
+ if (rc_baton->error.Fail())
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+
+ rc_baton->error = rc_baton->platform_ptr->CreateSymlink(dst_file.GetPath().c_str(), buf);
+
+ if (rc_baton->error.Fail())
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+
+ return FileSpec::eEnumerateDirectoryResultNext;
+ }
+ break;
+ case FileSpec::eFileTypeRegular:
+ {
+ // copy the file and keep going
+ FileSpec dst_file = rc_baton->dst;
+ if (!dst_file.GetFilename())
+ dst_file.GetFilename() = src.GetFilename();
+ Error err = rc_baton->platform_ptr->PutFile(src, dst_file);
+ if (err.Fail())
+ {
+ rc_baton->error.SetErrorString(err.AsCString());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ }
+ return FileSpec::eEnumerateDirectoryResultNext;
+ }
+ break;
+
+ case FileSpec::eFileTypeInvalid:
+ case FileSpec::eFileTypeOther:
+ case FileSpec::eFileTypeUnknown:
+ rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str());
+ return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ break;
+ }
+}
+
+Error
+Platform::Install (const FileSpec& src, const FileSpec& dst)
+{
+ Error error;
+
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf ("Platform::Install (src='%s', dst='%s')", src.GetPath().c_str(), dst.GetPath().c_str());
+ FileSpec fixed_dst(dst);
+
+ if (!fixed_dst.GetFilename())
+ fixed_dst.GetFilename() = src.GetFilename();
+
+ ConstString working_dir = GetWorkingDirectory();
+
+ if (dst)
+ {
+ if (dst.GetDirectory())
+ {
+ const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];
+ if (first_dst_dir_char == '/' || first_dst_dir_char == '\\')
+ {
+ fixed_dst.GetDirectory() = dst.GetDirectory();
+ }
+ // If the fixed destination file doesn't have a directory yet,
+ // then we must have a relative path. We will resolve this relative
+ // path against the platform's working directory
+ if (!fixed_dst.GetDirectory())
+ {
+ FileSpec relative_spec;
+ std::string path;
+ if (working_dir)
+ {
+ relative_spec.SetFile(working_dir.GetCString(), false);
+ relative_spec.AppendPathComponent(dst.GetPath().c_str());
+ fixed_dst.GetDirectory() = relative_spec.GetDirectory();
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
+ return error;
+ }
+ }
+ }
+ else
+ {
+ if (working_dir)
+ {
+ fixed_dst.GetDirectory() = working_dir;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("platform working directory must be valid for relative path '%s'", dst.GetPath().c_str());
+ return error;
+ }
+ }
+ }
+ else
+ {
+ if (working_dir)
+ {
+ fixed_dst.GetDirectory() = working_dir;
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("platform working directory must be valid when destination directory is empty");
+ return error;
+ }
+ }
+
+ if (log)
+ log->Printf ("Platform::Install (src='%s', dst='%s') fixed_dst='%s'", src.GetPath().c_str(), dst.GetPath().c_str(), fixed_dst.GetPath().c_str());
+
+ if (GetSupportsRSync())
+ {
+ error = PutFile(src, dst);
+ }
+ else
+ {
+ switch (src.GetFileType())
+ {
+ case FileSpec::eFileTypeDirectory:
+ {
+ if (GetFileExists (fixed_dst))
+ Unlink (fixed_dst.GetPath().c_str());
+ uint32_t permissions = src.GetPermissions();
+ if (permissions == 0)
+ permissions = eFilePermissionsDirectoryDefault;
+ std::string dst_dir_path(fixed_dst.GetPath());
+ error = MakeDirectory(dst_dir_path.c_str(), permissions);
+ if (error.Success())
+ {
+ // Make a filespec that only fills in the directory of a FileSpec so
+ // when we enumerate we can quickly fill in the filename for dst copies
+ FileSpec recurse_dst;
+ recurse_dst.GetDirectory().SetCString(dst_dir_path.c_str());
+ std::string src_dir_path (src.GetPath());
+ RecurseCopyBaton baton = { recurse_dst, this, Error() };
+ FileSpec::EnumerateDirectory(src_dir_path.c_str(), true, true, true, RecurseCopy_Callback, &baton);
+ return baton.error;
+ }
+ }
+ break;
+
+ case FileSpec::eFileTypeRegular:
+ if (GetFileExists (fixed_dst))
+ Unlink (fixed_dst.GetPath().c_str());
+ error = PutFile(src, fixed_dst);
+ break;
+
+ case FileSpec::eFileTypeSymbolicLink:
+ {
+ if (GetFileExists (fixed_dst))
+ Unlink (fixed_dst.GetPath().c_str());
+ char buf[PATH_MAX];
+ error = Host::Readlink(src.GetPath().c_str(), buf, sizeof(buf));
+ if (error.Success())
+ error = CreateSymlink(dst.GetPath().c_str(), buf);
+ }
+ break;
+ case FileSpec::eFileTypePipe:
+ error.SetErrorString("platform install doesn't handle pipes");
+ break;
+ case FileSpec::eFileTypeSocket:
+ error.SetErrorString("platform install doesn't handle sockets");
+ break;
+ case FileSpec::eFileTypeInvalid:
+ case FileSpec::eFileTypeUnknown:
+ case FileSpec::eFileTypeOther:
+ error.SetErrorString("platform install doesn't handle non file or directory items");
+ break;
+ }
+ }
+ return error;
+}
+
+bool
+Platform::SetWorkingDirectory (const ConstString &path)
+{
+ if (IsHost())
+ {
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf("Platform::SetWorkingDirectory('%s')", path.GetCString());
+#ifdef _WIN32
+ // Not implemented on Windows
+ return false;
+#else
+ if (path)
+ {
+ if (chdir(path.GetCString()) == 0)
+ return true;
+ }
+ return false;
+#endif
+ }
+ else
+ {
+ m_working_dir.Clear();
+ return SetRemoteWorkingDirectory(path);
+ }
+}
+
+Error
+Platform::MakeDirectory (const char *path, uint32_t permissions)
+{
+ if (IsHost())
+ return Host::MakeDirectory (path, permissions);
+ else
+ {
+ Error error;
+ error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
+ return error;
+ }
+}
+
+Error
+Platform::GetFilePermissions (const char *path, uint32_t &file_permissions)
+{
+ if (IsHost())
+ return Host::GetFilePermissions(path, file_permissions);
+ else
+ {
+ Error error;
+ error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
+ return error;
+ }
+}
+
+Error
+Platform::SetFilePermissions (const char *path, uint32_t file_permissions)
+{
+ if (IsHost())
+ return Host::SetFilePermissions(path, file_permissions);
+ else
+ {
+ Error error;
+ error.SetErrorStringWithFormat("remote platform %s doesn't support %s", GetPluginName().GetCString(), __PRETTY_FUNCTION__);
+ return error;
+ }
+}
+
+ConstString
Platform::GetName ()
{
- const char *name = GetHostname();
- if (name == NULL || name[0] == '\0')
- return GetPluginName();
- return ConstString (name);
+ return GetPluginName();
}
const char *
@@ -424,6 +749,16 @@ Platform::GetHostname ()
return m_name.c_str();
}
+bool
+Platform::SetRemoteWorkingDirectory(const ConstString &path)
+{
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
+ if (log)
+ log->Printf("Platform::SetRemoteWorkingDirectory('%s')", path.GetCString());
+ m_working_dir = path;
+ return true;
+}
+
const char *
Platform::GetUserName (uint32_t uid)
{
@@ -779,14 +1114,6 @@ Platform::IsCompatibleArchitecture (const ArchSpec &arch, bool exact_arch_match,
return false;
}
-uint32_t
-Platform::MakeDirectory (const FileSpec &spec,
- mode_t mode)
-{
- std::string path(spec.GetPath());
- return this->MakeDirectory(path,mode);
-}
-
Error
Platform::PutFile (const FileSpec& source,
const FileSpec& destination,
@@ -805,12 +1132,29 @@ Platform::GetFile (const FileSpec& source,
return error;
}
+Error
+Platform::CreateSymlink (const char *src, // The name of the link is in src
+ const char *dst)// The symlink points to dst
+{
+ Error error("unimplemented");
+ return error;
+}
+
bool
Platform::GetFileExists (const lldb_private::FileSpec& file_spec)
{
return false;
}
+Error
+Platform::Unlink (const char *path)
+{
+ Error error("unimplemented");
+ return error;
+}
+
+
+
lldb_private::Error
Platform::RunShellCommand (const char *command, // Shouldn't be NULL
const char *working_dir, // Pass NULL to use the current working directory
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index 700afdb7981a..1de322aee148 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -1023,6 +1023,8 @@ Process::Process(Target &target, Listener &listener) :
m_thread_mutex (Mutex::eMutexTypeRecursive),
m_thread_list_real (this),
m_thread_list (this),
+ m_extended_thread_list (this),
+ m_extended_thread_stop_id (0),
m_notifications (),
m_image_tokens (),
m_listener (listener),
@@ -1148,6 +1150,7 @@ Process::Finalize()
m_dyld_ap.reset();
m_thread_list_real.Destroy();
m_thread_list.Destroy();
+ m_extended_thread_list.Destroy();
std::vector<Notifications> empty_notifications;
m_notifications.swap(empty_notifications);
m_image_tokens.clear();
@@ -1591,6 +1594,13 @@ Process::UpdateThreadListIfNeeded ()
m_thread_list_real.Update(real_thread_list);
m_thread_list.Update (new_thread_list);
m_thread_list.SetStopID (stop_id);
+
+ if (GetLastNaturalStopID () != m_extended_thread_stop_id)
+ {
+ // Clear any extended threads that we may have accumulated previously
+ m_extended_thread_list.Clear();
+ m_extended_thread_stop_id = GetLastNaturalStopID ();
+ }
}
}
}
@@ -2103,12 +2113,37 @@ Process::CreateBreakpointSite (const BreakpointLocationSP &owner, bool use_hardw
}
else
{
- // Report error for setting breakpoint...
- m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
- load_addr,
- owner->GetBreakpoint().GetID(),
- owner->GetID(),
- error.AsCString() ? error.AsCString() : "unkown error");
+ bool show_error = true;
+ switch (GetState())
+ {
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateConnected:
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateDetached:
+ case eStateExited:
+ show_error = false;
+ break;
+
+ case eStateStopped:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateCrashed:
+ case eStateSuspended:
+ show_error = IsAlive();
+ break;
+ }
+
+ if (show_error)
+ {
+ // Report error for setting breakpoint...
+ m_target.GetDebugger().GetErrorFile().Printf ("warning: failed to set breakpoint site at 0x%" PRIx64 " for breakpoint %i.%i: %s\n",
+ load_addr,
+ owner->GetBreakpoint().GetID(),
+ owner->GetID(),
+ error.AsCString() ? error.AsCString() : "unkown error");
+ }
}
}
}
@@ -2350,6 +2385,7 @@ Process::DisableSoftwareBreakpoint (BreakpointSite *bp_site)
size_t
Process::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
{
+ error.Clear();
if (!GetDisableMemoryCache())
{
#if defined (VERIFY_MEMORY_READS)
@@ -2873,7 +2909,7 @@ Process::WaitForProcessStopPrivate (const TimeValue *timeout, EventSP &event_sp)
}
Error
-Process::Launch (const ProcessLaunchInfo &launch_info)
+Process::Launch (ProcessLaunchInfo &launch_info)
{
Error error;
m_abi_sp.reset();
@@ -2891,6 +2927,13 @@ Process::Launch (const ProcessLaunchInfo &launch_info)
exe_module->GetPlatformFileSpec().GetPath(platform_exec_file_path, sizeof(platform_exec_file_path));
if (exe_module->GetFileSpec().Exists())
{
+ // Install anything that might need to be installed prior to launching.
+ // For host systems, this will do nothing, but if we are connected to a
+ // remote platform it will install any needed binaries
+ error = GetTarget().Install(&launch_info);
+ if (error.Fail())
+ return error;
+
if (PrivateStateThreadIsValid ())
PausePrivateStateThread ();
@@ -4697,11 +4740,7 @@ Process::SettingsTerminate ()
ExecutionResults
Process::RunThreadPlan (ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
- bool stop_others,
- bool run_others,
- bool unwind_on_error,
- bool ignore_breakpoints,
- uint32_t timeout_usec,
+ const EvaluateExpressionOptions &options,
Stream &errors)
{
ExecutionResults return_value = eExecutionSetupError;
@@ -4812,6 +4851,17 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
thread->QueueThreadPlan(thread_plan_sp, false); // This used to pass "true" does that make sense?
+ if (options.GetDebug())
+ {
+ // In this case, we aren't actually going to run, we just want to stop right away.
+ // Flush this thread so we will refetch the stacks and show the correct backtrace.
+ // FIXME: To make this prettier we should invent some stop reason for this, but that
+ // is only cosmetic, and this functionality is only of use to lldb developers who can
+ // live with not pretty...
+ thread->Flush();
+ return eExecutionStoppedForDebug;
+ }
+
Listener listener("lldb.process.listener.run-thread-plan");
lldb::EventSP event_to_broadcast_sp;
@@ -4853,11 +4903,12 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
TimeValue one_thread_timeout = TimeValue::Now();
TimeValue final_timeout = one_thread_timeout;
- if (run_others)
+ uint32_t timeout_usec = options.GetTimeoutUsec();
+ if (options.GetTryAllThreads())
{
// If we are running all threads then we take half the time to run all threads, bounded by
// .25 sec.
- if (timeout_usec == 0)
+ if (options.GetTimeoutUsec() == 0)
one_thread_timeout.OffsetWithMicroSeconds(default_one_thread_timeout_usec);
else
{
@@ -4969,7 +5020,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (before_first_timeout)
{
- if (run_others)
+ if (options.GetTryAllThreads())
timeout_ptr = &one_thread_timeout;
else
{
@@ -5085,7 +5136,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->Printf ("Process::RunThreadPlan() stopped for breakpoint: %s.", stop_info_sp->GetDescription());
return_value = eExecutionHitBreakpoint;
- if (!ignore_breakpoints)
+ if (!options.DoesIgnoreBreakpoints())
{
event_to_broadcast_sp = event_sp;
}
@@ -5094,7 +5145,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString ("Process::RunThreadPlan(): thread plan didn't successfully complete.");
- if (!unwind_on_error)
+ if (!options.DoesUnwindOnError())
event_to_broadcast_sp = event_sp;
return_value = eExecutionInterrupted;
}
@@ -5145,7 +5196,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// either exit, or try with all threads running for the same timeout.
if (log) {
- if (run_others)
+ if (options.GetTryAllThreads())
{
uint64_t remaining_time = final_timeout - TimeValue::Now();
if (before_first_timeout)
@@ -5228,7 +5279,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
continue;
}
- if (!run_others)
+ if (!options.GetTryAllThreads())
{
if (log)
log->PutCString ("Process::RunThreadPlan(): try_all_threads was false, we stopped so now we're quitting.");
@@ -5301,8 +5352,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
// 1) The execution successfully completed
// 2) We hit a breakpoint, and ignore_breakpoints was true
// 3) We got some other error, and discard_on_error was true
- bool should_unwind = (return_value == eExecutionInterrupted && unwind_on_error)
- || (return_value == eExecutionHitBreakpoint && ignore_breakpoints);
+ bool should_unwind = (return_value == eExecutionInterrupted && options.DoesUnwindOnError())
+ || (return_value == eExecutionHitBreakpoint && options.DoesIgnoreBreakpoints());
if (return_value == eExecutionCompleted
|| should_unwind)
@@ -5422,7 +5473,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
if (log)
log->PutCString("Process::RunThreadPlan(): execution set up error.");
- if (unwind_on_error)
+ if (options.DoesUnwindOnError())
{
thread->DiscardThreadPlansUpToPlan (thread_plan_sp);
thread_plan_sp->SetPrivate (orig_plan_private);
@@ -5446,7 +5497,7 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx,
{
if (log)
log->PutCString("Process::RunThreadPlan(): thread plan stopped in mid course");
- if (unwind_on_error && thread_plan_sp)
+ if (options.DoesUnwindOnError() && thread_plan_sp)
{
if (log)
log->PutCString("Process::RunThreadPlan(): discarding thread plan 'cause unwind_on_error is set.");
@@ -5518,6 +5569,9 @@ Process::ExecutionResultAsCString (ExecutionResults result)
case eExecutionTimedOut:
result_name = "eExecutionTimedOut";
break;
+ case eExecutionStoppedForDebug:
+ result_name = "eExecutionStoppedForDebug";
+ break;
}
return result_name;
}
@@ -5633,7 +5687,7 @@ Process::DidExec ()
{
Target &target = GetTarget();
target.CleanupProcess ();
- target.ClearModules();
+ target.ClearModules(false);
m_dynamic_checkers_ap.reset();
m_abi_sp.reset();
m_system_runtime_ap.reset();
@@ -5649,5 +5703,9 @@ Process::DidExec ()
// Flush the process (threads and all stack frames) after running CompleteAttach()
// in case the dynamic loader loaded things in new locations.
Flush();
+
+ // After we figure out what was loaded/unloaded in CompleteAttach,
+ // we need to let the target know so it can do any cleanup it needs to.
+ target.DidExec();
}
diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp
index 3d68ba8706c9..93dce3ea0edc 100644
--- a/source/Target/RegisterContext.cpp
+++ b/source/Target/RegisterContext.cpp
@@ -440,6 +440,18 @@ RegisterContext::WriteRegisterValueToMemory (const RegisterInfo *reg_info,
}
+bool
+RegisterContext::ReadAllRegisterValues (lldb_private::RegisterCheckpoint &reg_checkpoint)
+{
+ return ReadAllRegisterValues(reg_checkpoint.GetData());
+}
+
+bool
+RegisterContext::WriteAllRegisterValues (const lldb_private::RegisterCheckpoint &reg_checkpoint)
+{
+ return WriteAllRegisterValues(reg_checkpoint.GetData());
+}
+
TargetSP
RegisterContext::CalculateTarget ()
{
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
index eaac3613c93d..631a77bd4951 100644
--- a/source/Target/StackFrameList.cpp
+++ b/source/Target/StackFrameList.cpp
@@ -301,7 +301,7 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
if (reg_ctx_sp)
{
- const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ const bool success = unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
// There shouldn't be any way not to get the frame info for frame 0.
// But if the unwinder can't make one, lets make one by hand with the
// SP as the CFA and see if that gets any further.
@@ -329,7 +329,7 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
}
else
{
- const bool success = unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ const bool success = unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
if (!success)
{
// We've gotten to the end of the stack.
@@ -451,14 +451,17 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx)
{
if (end_idx < m_concrete_frames_fetched)
return;
-
- uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
- if (num_frames <= end_idx + 1)
+
+ if (unwinder)
{
- //Done unwinding.
- m_concrete_frames_fetched = UINT32_MAX;
+ uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
+ if (num_frames <= end_idx + 1)
+ {
+ //Done unwinding.
+ m_concrete_frames_fetched = UINT32_MAX;
+ }
+ m_frames.resize(num_frames);
}
- m_frames.resize(num_frames);
}
}
diff --git a/source/Target/SystemRuntime.cpp b/source/Target/SystemRuntime.cpp
index 7ce150f41273..5c07ed388ae4 100644
--- a/source/Target/SystemRuntime.cpp
+++ b/source/Target/SystemRuntime.cpp
@@ -33,7 +33,8 @@ SystemRuntime::FindPlugin (Process *process)
// SystemRuntime constructor
//----------------------------------------------------------------------
SystemRuntime::SystemRuntime(Process *process) :
- m_process (process)
+ m_process (process),
+ m_types ()
{
}
@@ -59,15 +60,14 @@ SystemRuntime::ModulesDidLoad (ModuleList &module_list)
{
}
-std::vector<ConstString>
+const std::vector<ConstString> &
SystemRuntime::GetExtendedBacktraceTypes ()
{
- std::vector<ConstString> types;
- return types;
+ return m_types;
}
ThreadSP
-SystemRuntime::GetExtendedBacktrace (ThreadSP thread, ConstString type)
+SystemRuntime::GetExtendedBacktraceThread (ThreadSP thread, ConstString type)
{
return ThreadSP();
}
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 18efd8cb7247..fd9626a5de8d 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -192,7 +192,7 @@ Target::Destroy()
DeleteCurrentProcess ();
m_platform_sp.reset();
m_arch.Clear();
- ClearModules();
+ ClearModules(true);
m_section_load_list.Clear();
const bool notify = false;
m_breakpoint_list.RemoveAll(notify);
@@ -1014,9 +1014,9 @@ LoadScriptingResourceForModule (const ModuleSP &module_sp, Target *target)
}
void
-Target::ClearModules()
+Target::ClearModules(bool delete_locations)
{
- ModulesDidUnload (m_images, true);
+ ModulesDidUnload (m_images, delete_locations);
GetSectionLoadList().Clear();
m_images.Clear();
m_scratch_ast_context_ap.reset();
@@ -1025,10 +1025,18 @@ Target::ClearModules()
}
void
+Target::DidExec ()
+{
+ // When a process exec's we need to know about it so we can do some cleanup.
+ m_breakpoint_list.RemoveInvalidLocations(m_arch);
+ m_internal_breakpoint_list.RemoveInvalidLocations(m_arch);
+}
+
+void
Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TARGET));
- ClearModules();
+ ClearModules(false);
if (executable_sp.get())
{
@@ -1098,7 +1106,7 @@ Target::SetArchitecture (const ArchSpec &arch_spec)
m_arch = arch_spec;
ModuleSP executable_sp = GetExecutableModule ();
- ClearModules();
+ ClearModules(true);
// Need to do something about unsetting breakpoints.
if (executable_sp)
@@ -2182,12 +2190,78 @@ Target::RunStopHooks ()
result.GetImmediateErrorStream()->Flush();
}
+const TargetPropertiesSP &
+Target::GetGlobalProperties()
+{
+ static TargetPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ {
+ g_settings_sp.reset (new TargetProperties (NULL));
+ }
+ return g_settings_sp;
+}
+
+Error
+Target::Install (ProcessLaunchInfo *launch_info)
+{
+ Error error;
+ PlatformSP platform_sp (GetPlatform());
+ if (platform_sp)
+ {
+ if (platform_sp->IsRemote())
+ {
+ if (platform_sp->IsConnected())
+ {
+ // Install all files that have an install path, and always install the
+ // main executable when connected to a remote platform
+ const ModuleList& modules = GetImages();
+ const size_t num_images = modules.GetSize();
+ for (size_t idx = 0; idx < num_images; ++idx)
+ {
+ const bool is_main_executable = idx == 0;
+ ModuleSP module_sp(modules.GetModuleAtIndex(idx));
+ if (module_sp)
+ {
+ FileSpec local_file (module_sp->GetFileSpec());
+ if (local_file)
+ {
+ FileSpec remote_file (module_sp->GetRemoteInstallFileSpec());
+ if (!remote_file)
+ {
+ if (is_main_executable) // TODO: add setting for always installing main executable???
+ {
+ // Always install the main executable
+ remote_file.GetDirectory() = platform_sp->GetWorkingDirectory();
+ remote_file.GetFilename() = module_sp->GetFileSpec().GetFilename();
+ }
+ }
+ if (remote_file)
+ {
+ error = platform_sp->Install(local_file, remote_file);
+ if (error.Success())
+ {
+ module_sp->SetPlatformFileSpec(remote_file);
+ if (is_main_executable)
+ {
+ if (launch_info)
+ launch_info->SetExecutableFile(remote_file, false);
+ }
+ }
+ else
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return error;
+}
//--------------------------------------------------------------
-// class Target::StopHook
+// Target::StopHook
//--------------------------------------------------------------
-
-
Target::StopHook::StopHook (lldb::TargetSP target_sp, lldb::user_id_t uid) :
UserID (uid),
m_target_sp (target_sp),
@@ -2519,6 +2593,9 @@ protected:
mutable bool m_got_host_env;
};
+//----------------------------------------------------------------------
+// TargetProperties
+//----------------------------------------------------------------------
TargetProperties::TargetProperties (Target *target) :
Properties ()
{
@@ -2807,17 +2884,10 @@ TargetProperties::GetMemoryModuleLoadLevel() const
}
-const TargetPropertiesSP &
-Target::GetGlobalProperties()
-{
- static TargetPropertiesSP g_settings_sp;
- if (!g_settings_sp)
- {
- g_settings_sp.reset (new TargetProperties (NULL));
- }
- return g_settings_sp;
-}
+//----------------------------------------------------------------------
+// Target::TargetEventData
+//----------------------------------------------------------------------
const ConstString &
Target::TargetEventData::GetFlavorString ()
{
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 98c26019b4a1..07f5321990b2 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -496,7 +496,19 @@ Thread::ThreadStoppedForAReason (void)
bool
Thread::CheckpointThreadState (ThreadStateCheckpoint &saved_state)
{
- if (!SaveFrameZeroState(saved_state.register_backup))
+ saved_state.register_backup_sp.reset();
+ lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
+ if (frame_sp)
+ {
+ lldb::RegisterCheckpointSP reg_checkpoint_sp(new RegisterCheckpoint(RegisterCheckpoint::Reason::eExpression));
+ if (reg_checkpoint_sp)
+ {
+ lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext());
+ if (reg_ctx_sp && reg_ctx_sp->ReadAllRegisterValues (*reg_checkpoint_sp))
+ saved_state.register_backup_sp = reg_checkpoint_sp;
+ }
+ }
+ if (!saved_state.register_backup_sp)
return false;
saved_state.stop_info_sp = GetStopInfo();
@@ -511,8 +523,26 @@ Thread::CheckpointThreadState (ThreadStateCheckpoint &saved_state)
bool
Thread::RestoreRegisterStateFromCheckpoint (ThreadStateCheckpoint &saved_state)
{
- RestoreSaveFrameZero(saved_state.register_backup);
- return true;
+ if (saved_state.register_backup_sp)
+ {
+ lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
+ if (frame_sp)
+ {
+ lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext());
+ if (reg_ctx_sp)
+ {
+ bool ret = reg_ctx_sp->WriteAllRegisterValues (*saved_state.register_backup_sp);
+
+ // Clear out all stack frames as our world just changed.
+ ClearStackFrames();
+ reg_ctx_sp->InvalidateIfNeeded(true);
+ if (m_unwinder_ap.get())
+ m_unwinder_ap->Clear();
+ return ret;
+ }
+ }
+ }
+ return false;
}
bool
@@ -1420,14 +1450,6 @@ Thread::QueueThreadPlanForStepInRange
ThreadPlanSP
-Thread::QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans)
-{
- ThreadPlanSP thread_plan_sp (new ThreadPlanStepOverBreakpoint (*this));
- QueueThreadPlan (thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
-}
-
-ThreadPlanSP
Thread::QueueThreadPlanForStepOut
(
bool abort_other_plans,
@@ -1470,25 +1492,6 @@ Thread::QueueThreadPlanForStepThrough (StackID &return_stack_id, bool abort_othe
}
ThreadPlanSP
-Thread::QueueThreadPlanForCallFunction (bool abort_other_plans,
- Address& function,
- lldb::addr_t arg,
- bool stop_other_threads,
- bool unwind_on_error,
- bool ignore_breakpoints)
-{
- ThreadPlanSP thread_plan_sp (new ThreadPlanCallFunction (*this,
- function,
- ClangASTType(),
- arg,
- stop_other_threads,
- unwind_on_error,
- ignore_breakpoints));
- QueueThreadPlan (thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
-}
-
-ThreadPlanSP
Thread::QueueThreadPlanForRunToAddress (bool abort_other_plans,
Address &target_addr,
bool stop_other_threads)
@@ -1994,48 +1997,6 @@ Thread::GetStackFrameStatus (Stream& strm,
num_frames_with_source);
}
-bool
-Thread::SaveFrameZeroState (RegisterCheckpoint &checkpoint)
-{
- lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
- if (frame_sp)
- {
- checkpoint.SetStackID(frame_sp->GetStackID());
- lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext());
- if (reg_ctx_sp)
- return reg_ctx_sp->ReadAllRegisterValues (checkpoint.GetData());
- }
- return false;
-}
-
-bool
-Thread::RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint)
-{
- return ResetFrameZeroRegisters (checkpoint.GetData());
-}
-
-bool
-Thread::ResetFrameZeroRegisters (lldb::DataBufferSP register_data_sp)
-{
- lldb::StackFrameSP frame_sp(GetStackFrameAtIndex (0));
- if (frame_sp)
- {
- lldb::RegisterContextSP reg_ctx_sp (frame_sp->GetRegisterContext());
- if (reg_ctx_sp)
- {
- bool ret = reg_ctx_sp->WriteAllRegisterValues (register_data_sp);
-
- // Clear out all stack frames as our world just changed.
- ClearStackFrames();
- reg_ctx_sp->InvalidateIfNeeded(true);
- if (m_unwinder_ap.get())
- m_unwinder_ap->Clear();
- return ret;
- }
- }
- return false;
-}
-
Unwind *
Thread::GetUnwinder ()
{
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
index c9baaafffd6a..854750b85817 100644
--- a/source/Target/ThreadPlanCallFunction.cpp
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -55,8 +55,6 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
if (!abi)
return false;
- TargetSP target_sp (thread.CalculateTarget());
-
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
SetBreakpoints();
@@ -74,7 +72,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
return false;
}
- Module *exe_module = target_sp->GetExecutableModulePointer();
+ Module *exe_module = GetTarget().GetExecutableModulePointer();
if (exe_module == NULL)
{
@@ -107,7 +105,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
}
}
- start_load_addr = m_start_addr.GetLoadAddress (target_sp.get());
+ start_load_addr = m_start_addr.GetLoadAddress (&GetTarget());
// Checkpoint the thread state so we can restore it later.
if (log && log->GetVerbose())
@@ -120,7 +118,7 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
log->Printf ("ThreadPlanCallFunction(%p): %s.", this, m_constructor_errors.GetData());
return false;
}
- function_load_addr = m_function_addr.GetLoadAddress (target_sp.get());
+ function_load_addr = m_function_addr.GetLoadAddress (&GetTarget());
return true;
}
@@ -128,109 +126,36 @@ ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
const Address &function,
const ClangASTType &return_type,
- addr_t arg,
- bool stop_other_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- addr_t *this_arg,
- addr_t *cmd_arg) :
+ llvm::ArrayRef<addr_t> args,
+ const EvaluateExpressionOptions &options) :
ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
m_valid (false),
- m_stop_other_threads (stop_other_threads),
+ m_stop_other_threads (options.GetStopOthers()),
+ m_unwind_on_error (options.DoesUnwindOnError()),
+ m_ignore_breakpoints (options.DoesIgnoreBreakpoints()),
+ m_debug_execution (options.GetDebug()),
+ m_trap_exceptions (options.GetTrapExceptions()),
m_function_addr (function),
m_function_sp (0),
m_return_type (return_type),
m_takedown_done (false),
- m_stop_address (LLDB_INVALID_ADDRESS),
- m_unwind_on_error (unwind_on_error),
- m_ignore_breakpoints (ignore_breakpoints)
+ m_should_clear_objc_exception_bp(false),
+ m_should_clear_cxx_exception_bp (false),
+ m_stop_address (LLDB_INVALID_ADDRESS)
{
lldb::addr_t start_load_addr;
ABI *abi;
lldb::addr_t function_load_addr;
if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
return;
-
- if (this_arg && cmd_arg)
- {
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- this_arg,
- cmd_arg,
- &arg))
- return;
- }
- else if (this_arg)
- {
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- this_arg,
- &arg))
- return;
- }
- else
- {
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- &arg))
- return;
- }
-
- ReportRegisterState ("Function call was set up. Register state was:");
- m_valid = true;
-}
-
-
-ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
- const Address &function,
- const ClangASTType &return_type,
- bool stop_other_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- addr_t *arg1_ptr,
- addr_t *arg2_ptr,
- addr_t *arg3_ptr,
- addr_t *arg4_ptr,
- addr_t *arg5_ptr,
- addr_t *arg6_ptr) :
- ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
- m_valid (false),
- m_stop_other_threads (stop_other_threads),
- m_function_addr (function),
- m_function_sp (0),
- m_return_type (return_type),
- m_takedown_done (false),
- m_stop_address (LLDB_INVALID_ADDRESS),
- m_unwind_on_error (unwind_on_error),
- m_ignore_breakpoints (ignore_breakpoints)
-{
- lldb::addr_t start_load_addr;
- ABI *abi;
- lldb::addr_t function_load_addr;
- if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
+ if (!abi->PrepareTrivialCall(thread,
+ m_function_sp,
+ function_load_addr,
+ start_load_addr,
+ args))
return;
- if (!abi->PrepareTrivialCall (thread,
- m_function_sp,
- function_load_addr,
- start_load_addr,
- arg1_ptr,
- arg2_ptr,
- arg3_ptr,
- arg4_ptr,
- arg5_ptr,
- arg6_ptr))
- {
- return;
- }
-
ReportRegisterState ("Function call was set up. Register state was:");
m_valid = true;
@@ -299,7 +224,11 @@ ThreadPlanCallFunction::DoTakedown (bool success)
m_takedown_done = true;
m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
m_real_stop_info_sp = GetPrivateStopInfo ();
- m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state);
+ if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state))
+ {
+ if (log)
+ log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore register state", this);
+ }
SetPlanComplete(success);
ClearBreakpoints();
if (log && log->GetVerbose())
@@ -560,25 +489,34 @@ void
ThreadPlanCallFunction::SetBreakpoints ()
{
ProcessSP process_sp (m_thread.CalculateProcess());
- if (process_sp)
+ if (m_trap_exceptions && process_sp)
{
m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus);
m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC);
if (m_cxx_language_runtime)
+ {
+ m_should_clear_cxx_exception_bp = !m_cxx_language_runtime->ExceptionBreakpointsAreSet();
m_cxx_language_runtime->SetExceptionBreakpoints();
+ }
if (m_objc_language_runtime)
+ {
+ m_should_clear_objc_exception_bp = !m_objc_language_runtime->ExceptionBreakpointsAreSet();
m_objc_language_runtime->SetExceptionBreakpoints();
+ }
}
}
void
ThreadPlanCallFunction::ClearBreakpoints ()
{
- if (m_cxx_language_runtime)
- m_cxx_language_runtime->ClearExceptionBreakpoints();
- if (m_objc_language_runtime)
- m_objc_language_runtime->ClearExceptionBreakpoints();
+ if (m_trap_exceptions)
+ {
+ if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp)
+ m_cxx_language_runtime->ClearExceptionBreakpoints();
+ if (m_objc_language_runtime && m_should_clear_objc_exception_bp)
+ m_objc_language_runtime->ClearExceptionBreakpoints();
+ }
}
bool
@@ -586,21 +524,24 @@ ThreadPlanCallFunction::BreakpointsExplainStop()
{
StopInfoSP stop_info_sp = GetPrivateStopInfo ();
- if ((m_cxx_language_runtime &&
- m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
- ||(m_objc_language_runtime &&
- m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
+ if (m_trap_exceptions)
{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
- if (log)
- log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
-
- SetPlanComplete(false);
-
- // If the user has set the ObjC language breakpoint, it would normally get priority over our internal
- // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
- stop_info_sp->OverrideShouldStop (true);
- return true;
+ if ((m_cxx_language_runtime &&
+ m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
+ ||(m_objc_language_runtime &&
+ m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
+ {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
+ if (log)
+ log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
+
+ SetPlanComplete(false);
+
+ // If the user has set the ObjC language breakpoint, it would normally get priority over our internal
+ // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
+ stop_info_sp->OverrideShouldStop (true);
+ return true;
+ }
}
return false;
diff --git a/source/Target/ThreadPlanCallUserExpression.cpp b/source/Target/ThreadPlanCallUserExpression.cpp
index 70de1cbe86e1..827de3e6057a 100644
--- a/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/source/Target/ThreadPlanCallUserExpression.cpp
@@ -38,14 +38,10 @@ using namespace lldb_private;
ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread,
Address &function,
- lldb::addr_t arg,
- bool stop_other_threads,
- bool unwind_on_error,
- bool ignore_breakpoints,
- lldb::addr_t *this_arg,
- lldb::addr_t *cmd_arg,
+ llvm::ArrayRef<lldb::addr_t> args,
+ const EvaluateExpressionOptions &options,
ClangUserExpression::ClangUserExpressionSP &user_expression_sp) :
- ThreadPlanCallFunction (thread, function, ClangASTType(), arg, stop_other_threads, unwind_on_error, ignore_breakpoints, this_arg, cmd_arg),
+ ThreadPlanCallFunction (thread, function, ClangASTType(), args, options),
m_user_expression_sp (user_expression_sp)
{
// User expressions are generally "User generated" so we should set them up to stop when done.
diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp
index c1f14bd216de..2cfd29f89196 100644
--- a/source/Target/ThreadPlanStepInRange.cpp
+++ b/source/Target/ThreadPlanStepInRange.cpp
@@ -132,9 +132,9 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
bool stop_others;
if (m_stop_others == lldb::eOnlyThisThread)
- stop_others = false;
- else
stop_others = true;
+ else
+ stop_others = false;
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index d4ce470d56f3..9d2315708821 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -145,11 +145,10 @@ StringExtractor::GetChar (char fail_value)
uint8_t
StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
{
- uint32_t i = m_index;
- if ((i + 2) <= m_packet.size())
+ if (GetBytesLeft() >= 2)
{
- const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[i])];
- const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[i+1])];
+ const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index])];
+ const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index+1])];
if (hi_nibble < 16 && lo_nibble < 16)
{
m_index += 2;
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index 6e32481ccc50..08e7af725650 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -117,6 +117,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
case 'G':
if (PACKET_STARTS_WITH ("qGroupName:")) return eServerPacketType_qGroupName;
+ if (PACKET_MATCHES ("qGetWorkingDir")) return eServerPacketType_qGetWorkingDir;
break;
case 'H':
@@ -133,9 +134,10 @@ StringExtractorGDBRemote::GetServerPacketType () const
break;
case 'P':
- if (PACKET_STARTS_WITH ("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID;
- if (PACKET_STARTS_WITH ("qPlatform_RunCommand:")) return eServerPacketType_qPlatform_RunCommand;
- if (PACKET_STARTS_WITH ("qPlatform_IO_MkDir:")) return eServerPacketType_qPlatform_IO_MkDir;
+ if (PACKET_STARTS_WITH ("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID;
+ if (PACKET_STARTS_WITH ("qPlatform_shell:")) return eServerPacketType_qPlatform_shell;
+ if (PACKET_STARTS_WITH ("qPlatform_mkdir:")) return eServerPacketType_qPlatform_mkdir;
+ if (PACKET_STARTS_WITH ("qPlatform_chmod:")) return eServerPacketType_qPlatform_chmod;
break;
@@ -151,15 +153,17 @@ StringExtractorGDBRemote::GetServerPacketType () const
case 'v':
if (PACKET_STARTS_WITH("vFile:"))
{
- if (PACKET_STARTS_WITH("vFile:open:")) return eServerPacketType_vFile_Open;
- else if (PACKET_STARTS_WITH("vFile:close:")) return eServerPacketType_vFile_Close;
- else if (PACKET_STARTS_WITH("vFile:pread")) return eServerPacketType_vFile_pRead;
- else if (PACKET_STARTS_WITH("vFile:pwrite")) return eServerPacketType_vFile_pWrite;
- else if (PACKET_STARTS_WITH("vFile:size")) return eServerPacketType_vFile_Size;
- else if (PACKET_STARTS_WITH("vFile:exists")) return eServerPacketType_vFile_Exists;
- else if (PACKET_STARTS_WITH("vFile:stat")) return eServerPacketType_vFile_Stat;
- else if (PACKET_STARTS_WITH("vFile:mode")) return eServerPacketType_vFile_Mode;
- else if (PACKET_STARTS_WITH("vFile:MD5")) return eServerPacketType_vFile_MD5;
+ if (PACKET_STARTS_WITH("vFile:open:")) return eServerPacketType_vFile_open;
+ else if (PACKET_STARTS_WITH("vFile:close:")) return eServerPacketType_vFile_close;
+ else if (PACKET_STARTS_WITH("vFile:pread")) return eServerPacketType_vFile_pread;
+ else if (PACKET_STARTS_WITH("vFile:pwrite")) return eServerPacketType_vFile_pwrite;
+ else if (PACKET_STARTS_WITH("vFile:size")) return eServerPacketType_vFile_size;
+ else if (PACKET_STARTS_WITH("vFile:exists")) return eServerPacketType_vFile_exists;
+ else if (PACKET_STARTS_WITH("vFile:stat")) return eServerPacketType_vFile_stat;
+ else if (PACKET_STARTS_WITH("vFile:mode")) return eServerPacketType_vFile_mode;
+ else if (PACKET_STARTS_WITH("vFile:MD5")) return eServerPacketType_vFile_md5;
+ else if (PACKET_STARTS_WITH("vFile:symlink")) return eServerPacketType_vFile_symlink;
+ else if (PACKET_STARTS_WITH("vFile:unlink")) return eServerPacketType_vFile_unlink;
}
break;
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index fe500ecda5d4..2379882e8bf8 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -58,6 +58,7 @@ public:
eServerPacketType_qProcessInfoPID,
eServerPacketType_qSpeedTest,
eServerPacketType_qUserName,
+ eServerPacketType_qGetWorkingDir,
eServerPacketType_QEnvironment,
eServerPacketType_QLaunchArch,
eServerPacketType_QSetDisableASLR,
@@ -66,17 +67,20 @@ public:
eServerPacketType_QSetSTDERR,
eServerPacketType_QSetWorkingDir,
eServerPacketType_QStartNoAckMode,
- eServerPacketType_qPlatform_RunCommand,
- eServerPacketType_qPlatform_IO_MkDir,
- eServerPacketType_vFile_Open,
- eServerPacketType_vFile_Close,
- eServerPacketType_vFile_pRead,
- eServerPacketType_vFile_pWrite,
- eServerPacketType_vFile_Size,
- eServerPacketType_vFile_Mode,
- eServerPacketType_vFile_Exists,
- eServerPacketType_vFile_MD5,
- eServerPacketType_vFile_Stat
+ eServerPacketType_qPlatform_shell,
+ eServerPacketType_qPlatform_mkdir,
+ eServerPacketType_qPlatform_chmod,
+ eServerPacketType_vFile_open,
+ eServerPacketType_vFile_close,
+ eServerPacketType_vFile_pread,
+ eServerPacketType_vFile_pwrite,
+ eServerPacketType_vFile_size,
+ eServerPacketType_vFile_mode,
+ eServerPacketType_vFile_exists,
+ eServerPacketType_vFile_md5,
+ eServerPacketType_vFile_stat,
+ eServerPacketType_vFile_symlink,
+ eServerPacketType_vFile_unlink
};
ServerPacketType
diff --git a/source/lldb.cpp b/source/lldb.cpp
index c69563773915..78e8208e0910 100644
--- a/source/lldb.cpp
+++ b/source/lldb.cpp
@@ -60,6 +60,7 @@
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h"
+#include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h"
#endif
#include "Plugins/Process/mach-core/ProcessMachCore.h"
@@ -139,6 +140,7 @@ lldb_private::Initialize ()
PlatformRemoteiOS::Initialize();
PlatformMacOSX::Initialize();
PlatformiOSSimulator::Initialize();
+ SystemRuntimeMacOSX::Initialize();
#endif
#if defined (__linux__)
//----------------------------------------------------------------------
@@ -220,6 +222,7 @@ lldb_private::Terminate ()
PlatformDarwinKernel::Terminate();
PlatformRemoteiOS::Terminate();
PlatformiOSSimulator::Terminate();
+ SystemRuntimeMacOSX::Terminate();
#endif
Debugger::SettingsTerminate ();
diff --git a/tools/lldb-platform/lldb-platform.cpp b/tools/lldb-platform/lldb-platform.cpp
index 007e69c92814..bc9d62974771 100644
--- a/tools/lldb-platform/lldb-platform.cpp
+++ b/tools/lldb-platform/lldb-platform.cpp
@@ -21,11 +21,15 @@
// C++ Includes
// Other libraries and framework includes
+#include "lldb/lldb-private-log.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/ConnectionMachPort.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/OptionParser.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
using namespace lldb;
@@ -44,24 +48,32 @@ static struct option g_long_options[] =
{ "debug", no_argument, &g_debug, 1 },
{ "verbose", no_argument, &g_verbose, 1 },
{ "stay-alive", no_argument, &g_stay_alive, 1 },
- { "log-file", required_argument, NULL, 'l' },
- { "log-flags", required_argument, NULL, 'f' },
{ "listen", required_argument, NULL, 'L' },
+ { "port-offset", required_argument, NULL, 'p' },
+ { "gdbserver-port", required_argument, NULL, 'P' },
+ { "min-gdbserver-port", required_argument, NULL, 'm' },
+ { "max-gdbserver-port", required_argument, NULL, 'M' },
+ { "lldb-command", required_argument, NULL, 'c' },
{ NULL, 0, NULL, 0 }
};
+#if defined (__APPLE__)
+#define LOW_PORT (IPPORT_RESERVED)
+#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
+#else
+#define LOW_PORT (1024u)
+#define HIGH_PORT (49151u)
+#endif
+
+
//----------------------------------------------------------------------
// Watch for signals
//----------------------------------------------------------------------
-int g_sigpipe_received = 0;
void
signal_handler(int signo)
{
switch (signo)
{
- case SIGPIPE:
- g_sigpipe_received = 1;
- break;
case SIGHUP:
// Use SIGINT first, if that does not work, use SIGHUP as a last resort.
// And we should not call exit() here because it results in the global destructors
@@ -86,130 +98,165 @@ int
main (int argc, char *argv[])
{
const char *progname = argv[0];
- signal (SIGPIPE, signal_handler);
+ signal (SIGPIPE, SIG_IGN);
signal (SIGHUP, signal_handler);
int long_option_index = 0;
- StreamSP log_stream_sp;
- Args log_args;
Error error;
std::string listen_host_port;
int ch;
- Debugger::Initialize();
+ Debugger::Initialize(NULL);
+
+ lldb::DebuggerSP debugger_sp = Debugger::CreateInstance ();
+
+ debugger_sp->SetInputFileHandle(stdin, false);
+ debugger_sp->SetOutputFileHandle(stdout, false);
+ debugger_sp->SetErrorFileHandle(stderr, false);
-// ConnectionMachPort a;
-// ConnectionMachPort b;
-//
-// lldb::ConnectionStatus status;
-// const char *bootstrap_service_name = "HelloWorld";
-// status = a.BootstrapCheckIn(bootstrap_service_name, &error);
-//
-// if (status != eConnectionStatusSuccess)
-// {
-// fprintf(stderr, "%s", error.AsCString());
-// return 1;
-// }
-// status = b.BootstrapLookup (bootstrap_service_name, &error);
-// if (status != eConnectionStatusSuccess)
-// {
-// fprintf(stderr, "%s", error.AsCString());
-// return 2;
-// }
-//
-// if (a.Write ("hello", 5, status, &error) == 5)
-// {
-// char buf[32];
-// memset(buf, 0, sizeof(buf));
-// if (b.Read (buf, 5, status, &error))
-// {
-// printf("read returned bytes: %s", buf);
-// }
-// else
-// {
-// fprintf(stderr, "%s", error.AsCString());
-// return 4;
-// }
-// }
-// else
-// {
-// fprintf(stderr, "%s", error.AsCString());
-// return 3;
-// }
+ GDBRemoteCommunicationServer::PortMap gdbserver_portmap;
+ int min_gdbserver_port = 0;
+ int max_gdbserver_port = 0;
+ uint16_t port_offset = 0;
+
+ std::vector<std::string> lldb_commands;
+ bool show_usage = false;
+ int option_error = 0;
- while ((ch = getopt_long_only(argc, argv, "l:f:L:", g_long_options, &long_option_index)) != -1)
+ std::string short_options(OptionParser::GetShortOptionString(g_long_options));
+
+#if __GLIBC__
+ optind = 0;
+#else
+ optreset = 1;
+ optind = 1;
+#endif
+
+ while ((ch = getopt_long_only(argc, argv, short_options.c_str(), g_long_options, &long_option_index)) != -1)
{
-// DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
-// ch, (uint8_t)ch,
-// g_long_options[long_option_index].name,
-// g_long_options[long_option_index].has_arg ? '=' : ' ',
-// optarg ? optarg : "");
switch (ch)
{
case 0: // Any optional that auto set themselves will return 0
break;
- case 'l': // Set Log File
- if (optarg && optarg[0])
+ case 'L':
+ listen_host_port.append (optarg);
+ break;
+
+ case 'p':
{
- if ((strcasecmp(optarg, "stdout") == 0) || (strcmp(optarg, "/dev/stdout") == 0))
+ char *end = NULL;
+ long tmp_port_offset = strtoul(optarg, &end, 0);
+ if (end && *end == '\0')
{
- log_stream_sp.reset (new StreamFile (stdout, false));
+ if (LOW_PORT <= tmp_port_offset && tmp_port_offset <= HIGH_PORT)
+ {
+ port_offset = (uint16_t)tmp_port_offset;
+ }
+ else
+ {
+ fprintf (stderr, "error: port offset %li is not in the valid user port range of %u - %u\n", tmp_port_offset, LOW_PORT, HIGH_PORT);
+ option_error = 5;
+ }
}
- else if ((strcasecmp(optarg, "stderr") == 0) || (strcmp(optarg, "/dev/stderr") == 0))
+ else
{
- log_stream_sp.reset (new StreamFile (stderr, false));
+ fprintf (stderr, "error: invalid port offset string %s\n", optarg);
+ option_error = 4;
}
- else
+ }
+ break;
+
+ case 'P':
+ case 'm':
+ case 'M':
+ {
+ char *end = NULL;
+ long portnum = strtoul(optarg, &end, 0);
+ if (end && *end == '\0')
{
- FILE *log_file = fopen(optarg, "w");
- if (log_file)
+ if (LOW_PORT <= portnum && portnum <= HIGH_PORT)
{
- setlinebuf(log_file);
- log_stream_sp.reset (new StreamFile (log_file, true));
+ if (ch == 'P')
+ gdbserver_portmap[(uint16_t)portnum] = LLDB_INVALID_PROCESS_ID;
+ else if (ch == 'm')
+ min_gdbserver_port = portnum;
+ else
+ max_gdbserver_port = portnum;
}
else
{
- const char *errno_str = strerror(errno);
- fprintf (stderr, "Failed to open log file '%s' for writing: errno = %i (%s)", optarg, errno, errno_str ? errno_str : "unknown error");
+ fprintf (stderr, "error: port number %li is not in the valid user port range of %u - %u\n", portnum, LOW_PORT, HIGH_PORT);
+ option_error = 1;
}
-
}
-
+ else
+ {
+ fprintf (stderr, "error: invalid port number string %s\n", optarg);
+ option_error = 2;
+ }
}
break;
-
- case 'f': // Log Flags
- if (optarg && optarg[0])
- log_args.AppendArgument(optarg);
- break;
-
- case 'L':
- listen_host_port.append (optarg);
+
+ case 'c':
+ lldb_commands.push_back(optarg);
break;
case 'h': /* fall-through is intentional */
case '?':
- display_usage(progname);
+ show_usage = true;
break;
}
}
+
+ // Make a port map for a port range that was specified.
+ if (min_gdbserver_port < max_gdbserver_port)
+ {
+ for (uint16_t port = min_gdbserver_port; port < max_gdbserver_port; ++port)
+ gdbserver_portmap[port] = LLDB_INVALID_PROCESS_ID;
+ }
+ else if (min_gdbserver_port != max_gdbserver_port)
+ {
+ fprintf (stderr, "error: --min-gdbserver-port (%u) is greater than --max-gdbserver-port (%u)\n", min_gdbserver_port, max_gdbserver_port);
+ option_error = 3;
+
+ }
+
// Print usage and exit if no listening port is specified.
if (listen_host_port.empty())
- display_usage(progname);
+ show_usage = true;
- if (log_stream_sp)
+ if (show_usage || option_error)
{
- if (log_args.GetArgumentCount() == 0)
- log_args.AppendArgument("default");
- ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get());
+ display_usage(progname);
+ exit(option_error);
}
-
+
// Skip any options we consumed with getopt_long_only
argc -= optind;
argv += optind;
+ // Execute any LLDB commands that we were asked to evaluate.
+ for (const auto &lldb_command : lldb_commands)
+ {
+ lldb_private::CommandReturnObject result;
+ printf("(lldb) %s\n", lldb_command.c_str());
+ debugger_sp->GetCommandInterpreter().HandleCommand(lldb_command.c_str(), eLazyBoolNo, result);
+ const char *output = result.GetOutputData();
+ if (output && output[0])
+ puts(output);
+ }
+
do {
GDBRemoteCommunicationServer gdb_server (true);
+
+ if (port_offset > 0)
+ gdb_server.SetPortOffset(port_offset);
+
+ if (!gdbserver_portmap.empty())
+ {
+ gdb_server.SetPortMap(std::move(gdbserver_portmap));
+ }
+
if (!listen_host_port.empty())
{
std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());