summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-29 16:26:31 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-29 16:26:31 +0000
commit61b440f5005f0bf4e5864ba9cff4107ac56be404 (patch)
tree7d21c36d6cfd2c3053c6673f6303dceb45bc07c6
parentfb19dde5bfd42a03786ee50e6b300e47c45ace47 (diff)
downloadsrc-test2-61b440f5005f0bf4e5864ba9cff4107ac56be404.tar.gz
src-test2-61b440f5005f0bf4e5864ba9cff4107ac56be404.zip
Notes
-rw-r--r--docs/lldb-gdb-remote.txt157
-rw-r--r--include/lldb/API/SBStructuredData.h61
-rw-r--r--include/lldb/API/SBTrace.h13
-rw-r--r--include/lldb/Core/StructuredData.h86
-rw-r--r--include/lldb/Core/StructuredDataImpl.h73
-rw-r--r--include/lldb/Core/TraceOptions.h5
-rw-r--r--include/lldb/Host/Editline.h12
-rw-r--r--include/lldb/Host/common/NativeProcessProtocol.h105
-rw-r--r--include/lldb/Target/Process.h27
-rw-r--r--include/lldb/Utility/StringExtractor.h2
-rw-r--r--include/lldb/lldb-enumerations.h12
-rw-r--r--packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py65
-rw-r--r--packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp8
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile (renamed from packages/Python/lldbsuite/test/functionalities/thread/Makefile)2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py (renamed from packages/Python/lldbsuite/test/functionalities/thread/TestNumThreads.py)0
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp (renamed from packages/Python/lldbsuite/test/functionalities/thread/main.cpp)0
-rw-r--r--packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py206
-rw-r--r--scripts/interface/SBStructuredData.i25
-rw-r--r--scripts/lldb.swig18
-rw-r--r--source/API/SBProcess.cpp5
-rw-r--r--source/API/SBStructuredData.cpp44
-rw-r--r--source/API/SBThread.cpp11
-rw-r--r--source/API/SBTrace.cpp28
-rw-r--r--source/Commands/CommandObjectThread.cpp2
-rw-r--r--source/Core/FormatEntity.cpp12
-rw-r--r--source/Core/StructuredData.cpp4
-rw-r--r--source/Host/common/Editline.cpp8
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp7
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp4
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp31
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp206
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h21
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp241
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h8
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp26
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h16
-rw-r--r--source/Target/Process.cpp137
-rw-r--r--source/Target/Thread.cpp24
-rw-r--r--source/Utility/StringExtractor.cpp9
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp10
-rw-r--r--source/Utility/StringExtractorGDBRemote.h6
-rw-r--r--unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp226
-rw-r--r--unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp9
44 files changed, 1733 insertions, 241 deletions
diff --git a/docs/lldb-gdb-remote.txt b/docs/lldb-gdb-remote.txt
index 80a44e866cab..a4427a70444d 100644
--- a/docs/lldb-gdb-remote.txt
+++ b/docs/lldb-gdb-remote.txt
@@ -209,6 +209,163 @@ send packet: QListThreadsInStopReply
read packet: OK
//----------------------------------------------------------------------
+// jTraceStart:
+//
+// BRIEF
+// Packet for starting trace of type lldb::TraceType. The following
+// parameters should be appended to the packet formatted as a JSON
+// dictionary, where the schematic for the JSON dictionary in terms of
+// the recognized Keys is given below in the table.
+// Different tracing types could require different custom parameters.
+// Such custom tracing parameters if needed should be collectively
+// specified in a JSON dictionary and the dictionary can be appended
+// to this packet (as Value corresponding to "params"). Since sending
+// JSON data over gdb-remote protocol has certain limitations, binary
+// escaping convention should be used.
+//
+// Following is the list of parameters -
+//
+// Key Value (Integer) (O)Optional/
+// (except params which should be a (M)Mandatory
+// JSON dictionary)
+// ========== ====================================================
+//
+// type The type of trace to start (see M
+// lldb-enumerations for TraceType)
+//
+// buffersize The size of the buffer to allocate M
+// for trace gathering.
+//
+// threadid The id of the thread to start tracing O
+// on.
+//
+// metabuffersize The size of buffer to hold meta data O
+// used for decoding the trace data.
+//
+// params Any parameters that are specific to O
+// certain trace technologies should be
+// collectively specified as a JSON
+// dictionary
+// ========== ====================================================
+//
+// Each tracing instance is identified by a trace id which is returned
+// as the reply to this packet. In case the tracing failed to begin an
+// error code is returned instead.
+//----------------------------------------------------------------------
+
+send packet: jTraceStart:{"type":<type>,"buffersize":<buffersize>}]
+read packet: <trace id>/E<error code>
+
+//----------------------------------------------------------------------
+// jTraceStop:
+//
+// BRIEF
+// Stop tracing instance with trace id <trace id>, of course trace
+// needs to be started before. The following parameters should be
+// formatted as a JSON dictionary to the packet. Since sending
+// JSON data over gdb-remote protocol has certain limitations, binary
+// escaping convention should be used.
+//
+// Following is the list of parameters -
+//
+// Key Value (Integer) (O)Optional/
+// (M)Mandatory
+// ========== ====================================================
+//
+// traceid The trace id of the tracing instance M
+//
+// threadid The id of the thread to stop tracing O
+// on. Since <trace id> could map to
+// multiple trace instances (in case it
+// maps to the complete process), the
+// threadid of a particular thread could
+// be appended as "threadid:<thread id>;"
+// to stop tracing on that thread.
+// ========== ====================================================
+//
+// An OK response is sent in case of success else an error code is
+// returned.
+//----------------------------------------------------------------------
+
+send packet: jTraceStop:{"traceid":<trace id>}]
+read packet: <OK response>/E<error code>
+
+//----------------------------------------------------------------------
+// jTraceBufferRead:
+//
+// BRIEF
+// Packet for reading the trace for tracing instance <trace id>, i.e the
+// id obtained from StartTrace API. The following parameters should be
+// formatted as a JSON dictionary to the packet. Since sending
+// JSON data over gdb-remote protocol has certain limitations, binary
+// escaping convention should be used.
+//
+// Following is the list of parameters -
+//
+// Key Value (Integer) (O)Optional/
+// (M)Mandatory
+// ========== ====================================================
+// traceid The trace id of the tracing instance M
+//
+// offset The offset to start reading the data M
+// from.
+//
+// buffersize The size of the data intended to read. M
+//
+// threadid The id of the thread to retrieve data O
+// from.
+// ========== ====================================================
+//
+// The trace data is sent as raw binary data if the read was successful
+// else an error code is sent.
+//----------------------------------------------------------------------
+
+send packet: jTraceBufferRead:{"traceid":<trace id>,"offset":<byteoffset>,"buffersize":<byte_count>}]
+read packet: <binary trace data>/E<error code>
+
+//----------------------------------------------------------------------
+// jTraceMetaRead:
+//
+// BRIEF
+// Similar Packet as above except it reads meta data.
+//----------------------------------------------------------------------
+
+/----------------------------------------------------------------------
+// jTraceConfigRead:
+//
+// BRIEF
+// Request the trace configuration for the tracing instance with id
+// <trace id>.
+//
+// Following is the list of parameters -
+//
+// Key Value (Integer) (O)Optional/
+// (M)Mandatory
+// ========== ====================================================
+// traceid The trace id of the tracing instance M
+//
+// threadid The id of the thread to obtain trace O
+// configuration from. Since <trace id>
+// could map to multiple trace instances
+// (in case it maps to the complete
+// process), the threadid of a particular
+// thread could be appended as
+// "threadid:<thread id>;" to obtain the
+// trace configuration of that thread.
+// ========== ====================================================
+//
+// In the response packet the trace configuration is sent as text,
+// formatted as a JSON dictionary. Since sending JSON data over
+// gdb-remote protocol has certain limitations, binary escaping
+// convention is used.
+// In case the trace instance with the <trace id> was not found, an
+// error code is returned.
+//----------------------------------------------------------------------
+
+send packet: jTraceConfigRead:{"traceid":<trace id>}
+read packet: {"conf1":<conf1>,"conf2":<conf2>,"params":{"paramName":paramValue}]}];/E<error code>
+
+//----------------------------------------------------------------------
// "qRegisterInfo<hex-reg-id>"
//
// BRIEF
diff --git a/include/lldb/API/SBStructuredData.h b/include/lldb/API/SBStructuredData.h
index 5fb5d3be65ad..f7a6469bb8de 100644
--- a/include/lldb/API/SBStructuredData.h
+++ b/include/lldb/API/SBStructuredData.h
@@ -37,11 +37,70 @@ public:
lldb::SBError GetDescription(lldb::SBStream &stream) const;
+ //------------------------------------------------------------------
+ /// Return the type of data in this data structure
+ //------------------------------------------------------------------
+ lldb::StructuredDataType GetType() const;
+
+ //------------------------------------------------------------------
+ /// Return the size (i.e. number of elements) in this data structure
+ /// if it is an array or dictionary type. For other types, 0 will be
+ // returned.
+ //------------------------------------------------------------------
+ size_t GetSize() const;
+
+ //------------------------------------------------------------------
+ /// Return the value corresponding to a key if this data structure
+ /// is a dictionary type.
+ //------------------------------------------------------------------
+ lldb::SBStructuredData GetValueForKey(const char *key) const;
+
+ //------------------------------------------------------------------
+ /// Return the value corresponding to an index if this data structure
+ /// is array.
+ //------------------------------------------------------------------
+ lldb::SBStructuredData GetItemAtIndex(size_t idx) const;
+
+ //------------------------------------------------------------------
+ /// Return the integer value if this data structure is an integer type.
+ //------------------------------------------------------------------
+ uint64_t GetIntegerValue(uint64_t fail_value = 0) const;
+
+ //------------------------------------------------------------------
+ /// Return the floating point value if this data structure is a floating
+ /// type.
+ //------------------------------------------------------------------
+ double GetFloatValue(double fail_value = 0.0) const;
+
+ //------------------------------------------------------------------
+ /// Return the boolean value if this data structure is a boolean type.
+ //------------------------------------------------------------------
+ bool GetBooleanValue(bool fail_value = false) const;
+
+ //------------------------------------------------------------------
+ /// Provides the string value if this data structure is a string type.
+ ///
+ /// @param[out] dst
+ /// pointer where the string value will be written. In case it is null,
+ /// nothing will be written at @dst.
+ ///
+ /// @param[in] dst_len
+ /// max number of characters that can be written at @dst. In case it is
+ /// zero, nothing will be written at @dst. If this length is not enough
+ /// to write the complete string value, (dst_len-1) bytes of the string
+ /// value will be written at @dst followed by a null character.
+ ///
+ /// @return
+ /// Returns the byte size needed to completely write the string value at
+ /// @dst in all cases.
+ //------------------------------------------------------------------
+ size_t GetStringValue(char *dst, size_t dst_len) const;
+
protected:
friend class SBTraceOptions;
StructuredDataImplUP m_impl_up;
};
-}
+} // namespace lldb
#endif /* SBStructuredData_h */
diff --git a/include/lldb/API/SBTrace.h b/include/lldb/API/SBTrace.h
index e29a5db7cc46..244a01e5ce11 100644
--- a/include/lldb/API/SBTrace.h
+++ b/include/lldb/API/SBTrace.h
@@ -40,7 +40,7 @@ public:
///
/// @param[in] thread_id
/// Tracing could be started for the complete process or a
- /// single thread, in the first case the uid obtained would
+ /// single thread, in the first case the traceid obtained would
/// map to all the threads existing within the process and the
/// ones spawning later. The thread_id parameter can be used in
/// such a scenario to select the trace data for a specific
@@ -68,16 +68,17 @@ public:
/// An error explaining what went wrong.
///
/// @param[in] thread_id
- /// The user id could map to a tracing instance for a thread
+ /// The trace id could map to a tracing instance for a thread
/// or could also map to a group of threads being traced with
/// the same trace options. A thread_id is normally optional
/// except in the case of tracing a complete process and tracing
/// needs to switched off on a particular thread.
/// A situation could occur where initially a thread (lets say
- /// thread A) is being individually traced with a particular uid
- /// and then tracing is started on the complete process, in this
- /// case thread A will continue without any change. All newly
- /// spawned threads would be traced with the uid of the process.
+ /// thread A) is being individually traced with a particular
+ /// trace id and then tracing is started on the complete
+ /// process, in this case thread A will continue without any
+ /// change. All newly spawned threads would be traced with the
+ /// trace id of the process.
/// Now if the StopTrace API is called for the whole process,
/// thread A will not be stopped and must be stopped separately.
//------------------------------------------------------------------
diff --git a/include/lldb/Core/StructuredData.h b/include/lldb/Core/StructuredData.h
index 6cb78dc48ab5..39c2f04bb382 100644
--- a/include/lldb/Core/StructuredData.h
+++ b/include/lldb/Core/StructuredData.h
@@ -13,7 +13,8 @@
#include "llvm/ADT/StringRef.h"
#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
+#include "lldb/Utility/FileSpec.h" // for FileSpec
+#include "lldb/lldb-enumerations.h" // for StructuredDataType
#include <functional>
#include <map>
@@ -71,46 +72,38 @@ public:
typedef std::shared_ptr<Dictionary> DictionarySP;
typedef std::shared_ptr<Generic> GenericSP;
- enum class Type {
- eTypeInvalid = -1,
- eTypeNull = 0,
- eTypeGeneric,
- eTypeArray,
- eTypeInteger,
- eTypeFloat,
- eTypeBoolean,
- eTypeString,
- eTypeDictionary
- };
-
class Object : public std::enable_shared_from_this<Object> {
public:
- Object(Type t = Type::eTypeInvalid) : m_type(t) {}
+ Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid)
+ : m_type(t) {}
virtual ~Object() = default;
virtual bool IsValid() const { return true; }
- virtual void Clear() { m_type = Type::eTypeInvalid; }
+ virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; }
- Type GetType() const { return m_type; }
+ lldb::StructuredDataType GetType() const { return m_type; }
- void SetType(Type t) { m_type = t; }
+ void SetType(lldb::StructuredDataType t) { m_type = t; }
Array *GetAsArray() {
- return ((m_type == Type::eTypeArray) ? static_cast<Array *>(this)
- : nullptr);
+ return ((m_type == lldb::eStructuredDataTypeArray)
+ ? static_cast<Array *>(this)
+ : nullptr);
}
Dictionary *GetAsDictionary() {
- return ((m_type == Type::eTypeDictionary)
- ? static_cast<Dictionary *>(this)
- : nullptr);
+ return (
+ (m_type == lldb::eStructuredDataTypeDictionary)
+ ? static_cast<Dictionary *>(this)
+ : nullptr);
}
Integer *GetAsInteger() {
- return ((m_type == Type::eTypeInteger) ? static_cast<Integer *>(this)
- : nullptr);
+ return ((m_type == lldb::eStructuredDataTypeInteger)
+ ? static_cast<Integer *>(this)
+ : nullptr);
}
uint64_t GetIntegerValue(uint64_t fail_value = 0) {
@@ -119,8 +112,9 @@ public:
}
Float *GetAsFloat() {
- return ((m_type == Type::eTypeFloat) ? static_cast<Float *>(this)
- : nullptr);
+ return ((m_type == lldb::eStructuredDataTypeFloat)
+ ? static_cast<Float *>(this)
+ : nullptr);
}
double GetFloatValue(double fail_value = 0.0) {
@@ -129,8 +123,9 @@ public:
}
Boolean *GetAsBoolean() {
- return ((m_type == Type::eTypeBoolean) ? static_cast<Boolean *>(this)
- : nullptr);
+ return ((m_type == lldb::eStructuredDataTypeBoolean)
+ ? static_cast<Boolean *>(this)
+ : nullptr);
}
bool GetBooleanValue(bool fail_value = false) {
@@ -139,8 +134,9 @@ public:
}
String *GetAsString() {
- return ((m_type == Type::eTypeString) ? static_cast<String *>(this)
- : nullptr);
+ return ((m_type == lldb::eStructuredDataTypeString)
+ ? static_cast<String *>(this)
+ : nullptr);
}
llvm::StringRef GetStringValue(const char *fail_value = nullptr) {
@@ -152,8 +148,9 @@ public:
}
Generic *GetAsGeneric() {
- return ((m_type == Type::eTypeGeneric) ? static_cast<Generic *>(this)
- : nullptr);
+ return ((m_type == lldb::eStructuredDataTypeGeneric)
+ ? static_cast<Generic *>(this)
+ : nullptr);
}
ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
@@ -163,12 +160,12 @@ public:
virtual void Dump(Stream &s, bool pretty_print = true) const = 0;
private:
- Type m_type;
+ lldb::StructuredDataType m_type;
};
class Array : public Object {
public:
- Array() : Object(Type::eTypeArray) {}
+ Array() : Object(lldb::eStructuredDataTypeArray) {}
~Array() override = default;
@@ -288,7 +285,8 @@ public:
class Integer : public Object {
public:
- Integer(uint64_t i = 0) : Object(Type::eTypeInteger), m_value(i) {}
+ Integer(uint64_t i = 0)
+ : Object(lldb::eStructuredDataTypeInteger), m_value(i) {}
~Integer() override = default;
@@ -304,7 +302,8 @@ public:
class Float : public Object {
public:
- Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
+ Float(double d = 0.0) : Object(lldb::eStructuredDataTypeFloat),
+ m_value(d) {}
~Float() override = default;
@@ -320,7 +319,8 @@ public:
class Boolean : public Object {
public:
- Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
+ Boolean(bool b = false) : Object(lldb::eStructuredDataTypeBoolean),
+ m_value(b) {}
~Boolean() override = default;
@@ -336,9 +336,10 @@ public:
class String : public Object {
public:
- String() : Object(Type::eTypeString) {}
+ String() : Object(lldb::eStructuredDataTypeString) {}
explicit String(llvm::StringRef S)
- : Object(Type::eTypeString), m_value(S) {}
+ : Object(lldb::eStructuredDataTypeString),
+ m_value(S) {}
void SetValue(llvm::StringRef S) { m_value = S; }
@@ -352,7 +353,8 @@ public:
class Dictionary : public Object {
public:
- Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
+ Dictionary() : Object(lldb::eStructuredDataTypeDictionary),
+ m_dict() {}
~Dictionary() override = default;
@@ -522,7 +524,7 @@ public:
class Null : public Object {
public:
- Null() : Object(Type::eTypeNull) {}
+ Null() : Object(lldb::eStructuredDataTypeNull) {}
~Null() override = default;
@@ -534,7 +536,7 @@ public:
class Generic : public Object {
public:
explicit Generic(void *object = nullptr)
- : Object(Type::eTypeGeneric), m_object(object) {}
+ : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {}
void SetValue(void *value) { m_object = value; }
diff --git a/include/lldb/Core/StructuredDataImpl.h b/include/lldb/Core/StructuredDataImpl.h
index 81d59f83ac3d..92f0417b354a 100644
--- a/include/lldb/Core/StructuredDataImpl.h
+++ b/include/lldb/Core/StructuredDataImpl.h
@@ -15,7 +15,9 @@
#include "lldb/Target/StructuredDataPlugin.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
+#include "llvm/ADT/StringRef.h"
#pragma mark--
#pragma mark StructuredDataImpl
@@ -78,18 +80,77 @@ public:
return plugin_sp->GetDescription(m_data_sp, stream);
}
- StructuredData::ObjectSP GetObjectSP() {
- return m_data_sp;
+ StructuredData::ObjectSP GetObjectSP() { return m_data_sp; }
+
+ void SetObjectSP(const StructuredData::ObjectSP &obj) { m_data_sp = obj; }
+
+ lldb::StructuredDataType GetType() const {
+ return (m_data_sp ? m_data_sp->GetType() :
+ lldb::eStructuredDataTypeInvalid);
}
- void SetObjectSP(const StructuredData::ObjectSP &obj) {
- m_data_sp = obj;
+ size_t GetSize() const {
+ if (!m_data_sp)
+ return 0;
+
+ if (m_data_sp->GetType() == lldb::eStructuredDataTypeDictionary) {
+ auto dict = m_data_sp->GetAsDictionary();
+ return (dict->GetSize());
+ } else if (m_data_sp->GetType() == lldb::eStructuredDataTypeArray) {
+ auto array = m_data_sp->GetAsArray();
+ return (array->GetSize());
+ } else
+ return 0;
}
-private:
+ StructuredData::ObjectSP GetValueForKey(const char *key) const {
+ if (m_data_sp) {
+ auto dict = m_data_sp->GetAsDictionary();
+ if (dict)
+ return dict->GetValueForKey(llvm::StringRef(key));
+ }
+ return StructuredData::ObjectSP();
+ }
+
+ StructuredData::ObjectSP GetItemAtIndex(size_t idx) const {
+ if (m_data_sp) {
+ auto array = m_data_sp->GetAsArray();
+ if (array)
+ return array->GetItemAtIndex(idx);
+ }
+ return StructuredData::ObjectSP();
+ }
+
+ uint64_t GetIntegerValue(uint64_t fail_value = 0) const {
+ return (m_data_sp ? m_data_sp->GetIntegerValue(fail_value) : fail_value);
+ }
+ double GetFloatValue(double fail_value = 0.0) const {
+ return (m_data_sp ? m_data_sp->GetFloatValue(fail_value) : fail_value);
+ }
+
+ bool GetBooleanValue(bool fail_value = false) const {
+ return (m_data_sp ? m_data_sp->GetBooleanValue(fail_value) : fail_value);
+ }
+
+ size_t GetStringValue(char *dst, size_t dst_len) const {
+ if (!m_data_sp)
+ return 0;
+
+ llvm::StringRef result = m_data_sp->GetStringValue();
+ if (result.empty())
+ return 0;
+
+ if (!dst || !dst_len) {
+ char s[1];
+ return (::snprintf(s, 1, "%s", result.data()));
+ }
+ return (::snprintf(dst, dst_len, "%s", result.data()));
+ }
+
+private:
lldb::StructuredDataPluginWP m_plugin_wp;
StructuredData::ObjectSP m_data_sp;
};
-}
+} // namespace lldb_private
#endif
diff --git a/include/lldb/Core/TraceOptions.h b/include/lldb/Core/TraceOptions.h
index e875a531e870..91f48915c94b 100644
--- a/include/lldb/Core/TraceOptions.h
+++ b/include/lldb/Core/TraceOptions.h
@@ -18,8 +18,7 @@
namespace lldb_private {
class TraceOptions {
public:
- TraceOptions()
- : m_trace_params(new StructuredData::Dictionary()) {}
+ TraceOptions() : m_trace_params(new StructuredData::Dictionary()) {}
const StructuredData::DictionarySP &getTraceParams() const {
return m_trace_params;
@@ -43,7 +42,7 @@ public:
void setThreadID(lldb::tid_t thread_id) { m_thread_id = thread_id; }
- lldb::tid_t getThreadID() { return m_thread_id; }
+ lldb::tid_t getThreadID() const { return m_thread_id; }
private:
lldb::TraceType m_type;
diff --git a/include/lldb/Host/Editline.h b/include/lldb/Host/Editline.h
index 2b1a8e047261..0b75e9c923ca 100644
--- a/include/lldb/Host/Editline.h
+++ b/include/lldb/Host/Editline.h
@@ -82,8 +82,14 @@ using EditLineStringStreamType = std::stringstream;
using EditLineCharType = char;
#endif
+#ifdef EL_CLIENTDATA /* editline with wide support + wide char read function */
+using EditLineGetCharType = wchar_t;
+#else
+using EditLineGetCharType = char;
+#endif
+
typedef int (*EditlineGetCharCallbackType)(::EditLine *editline,
- EditLineCharType *c);
+ EditLineGetCharType *c);
typedef unsigned char (*EditlineCommandCallbackType)(::EditLine *editline,
int ch);
typedef const char *(*EditlinePromptCallbackType)(::EditLine *editline);
@@ -270,7 +276,7 @@ private:
/// Character reading implementation for EditLine that supports our multi-line
/// editing trickery.
- int GetCharacter(EditLineCharType *c);
+ int GetCharacter(EditLineGetCharType *c);
/// Prompt implementation for EditLine.
const char *Prompt();
@@ -323,7 +329,7 @@ private:
/// single or multi-line editing.
void ConfigureEditor(bool multiline);
- bool CompleteCharacter(char ch, EditLineCharType &out);
+ bool CompleteCharacter(char ch, EditLineGetCharType &out);
private:
#if LLDB_EDITLINE_USE_WCHAR
diff --git a/include/lldb/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h
index 388edef0578d..55eca0fa0b65 100644
--- a/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/include/lldb/Host/common/NativeProcessProtocol.h
@@ -10,6 +10,7 @@
#ifndef liblldb_NativeProcessProtocol_h_
#define liblldb_NativeProcessProtocol_h_
+#include "lldb/Core/TraceOptions.h"
#include "lldb/Host/MainLoop.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-forward.h"
@@ -308,6 +309,108 @@ public:
static Status Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
+ //------------------------------------------------------------------
+ /// StartTracing API for starting a tracing instance with the
+ /// TraceOptions on a specific thread or process.
+ ///
+ /// @param[in] config
+ /// The configuration to use when starting tracing.
+ ///
+ /// @param[out] error
+ /// Status indicates what went wrong.
+ ///
+ /// @return
+ /// The API returns a user_id which can be used to get trace
+ /// data, trace configuration or stopping the trace instance.
+ /// The user_id is a key to identify and operate with a tracing
+ /// instance. It may refer to the complete process or a single
+ /// thread.
+ //------------------------------------------------------------------
+ virtual lldb::user_id_t StartTrace(const TraceOptions &config,
+ Status &error) {
+ error.SetErrorString("Not implemented");
+ return LLDB_INVALID_UID;
+ }
+
+ //------------------------------------------------------------------
+ /// StopTracing API as the name suggests stops a tracing instance.
+ ///
+ /// @param[in] uid
+ /// The user id of the trace intended to be stopped. Now a
+ /// user_id may map to multiple threads in which case this API
+ /// could be used to stop the tracing for a specific thread by
+ /// supplying its thread id.
+ ///
+ /// @param[in] thread
+ /// Thread is needed when the complete process is being traced
+ /// and the user wishes to stop tracing on a particular thread.
+ ///
+ /// @return
+ /// Status indicating what went wrong.
+ //------------------------------------------------------------------
+ virtual Status StopTrace(lldb::user_id_t uid,
+ lldb::tid_t thread = LLDB_INVALID_THREAD_ID) {
+ return Status("Not implemented");
+ }
+
+ //------------------------------------------------------------------
+ /// This API provides the trace data collected in the form of raw
+ /// data.
+ ///
+ /// @param[in] uid thread
+ /// The uid and thread provide the context for the trace
+ /// instance.
+ ///
+ /// @param[in] buffer
+ /// The buffer provides the destination buffer where the trace
+ /// data would be read to. The buffer should be truncated to the
+ /// filled length by this function.
+ ///
+ /// @param[in] offset
+ /// There is possibility to read partially the trace data from
+ /// a specified offset where in such cases the buffer provided
+ /// may be smaller than the internal trace collection container.
+ ///
+ /// @return
+ /// The size of the data actually read.
+ //------------------------------------------------------------------
+ virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0) {
+ return Status("Not implemented");
+ }
+
+ //------------------------------------------------------------------
+ /// Similar API as above except it aims to provide any extra data
+ /// useful for decoding the actual trace data.
+ //------------------------------------------------------------------
+ virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0) {
+ return Status("Not implemented");
+ }
+
+ //------------------------------------------------------------------
+ /// API to query the TraceOptions for a given user id
+ ///
+ /// @param[in] uid
+ /// The user id of the tracing instance.
+ ///
+ /// @param[in] config
+ /// The thread id of the tracing instance, in case configuration
+ /// for a specific thread is needed should be specified in the
+ /// config.
+ ///
+ /// @param[out] error
+ /// Status indicates what went wrong.
+ ///
+ /// @param[out] config
+ /// The actual configuration being used for tracing.
+ //------------------------------------------------------------------
+ virtual Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &config) {
+ return Status("Not implemented");
+ }
+
protected:
lldb::pid_t m_pid;
@@ -381,6 +484,6 @@ protected:
private:
void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
};
-}
+} // namespace lldb_private
#endif // #ifndef liblldb_NativeProcessProtocol_h_
diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h
index d2ab85d1652a..dbf6cba09f43 100644
--- a/include/lldb/Target/Process.h
+++ b/include/lldb/Target/Process.h
@@ -2781,7 +2781,7 @@ public:
/// GetTraceConfig should supply the actual used trace
/// configuration.
//------------------------------------------------------------------
- virtual lldb::user_id_t StartTrace(lldb::TraceOptionsSP &options,
+ virtual lldb::user_id_t StartTrace(const TraceOptions &options,
Status &error) {
error.SetErrorString("Not implemented");
return LLDB_INVALID_UID;
@@ -2796,9 +2796,8 @@ public:
/// In the other case that tracing on an individual thread needs
/// to be stopped a thread_id can be supplied.
//------------------------------------------------------------------
- virtual void StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id,
- Status &error) {
- error.SetErrorString("Not implemented");
+ virtual Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
+ return Status("Not implemented");
}
//------------------------------------------------------------------
@@ -2809,21 +2808,19 @@ public:
/// may not. The thread_id should be used to select a particular
/// thread for trace extraction.
//------------------------------------------------------------------
- virtual size_t GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
- Status &error, void *buf, size_t size,
+ virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
size_t offset = 0) {
- error.SetErrorString("Not implemented");
- return 0;
+ return Status("Not implemented");
}
//------------------------------------------------------------------
/// Similar API as above except for obtaining meta data
//------------------------------------------------------------------
- virtual size_t GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
- Status &error, void *buf, size_t size,
+ virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
size_t offset = 0) {
- error.SetErrorString("Not implemented");
- return 0;
+ return Status("Not implemented");
}
//------------------------------------------------------------------
@@ -2835,10 +2832,8 @@ public:
/// configuration used by a specific thread. The thread_id specified
/// should also match the uid otherwise an error will be returned.
//------------------------------------------------------------------
- virtual void GetTraceConfig(lldb::user_id_t uid, Status &error,
- lldb::TraceOptionsSP &options) {
- error.SetErrorString("Not implemented");
- return;
+ virtual Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) {
+ return Status("Not implemented");
}
protected:
diff --git a/include/lldb/Utility/StringExtractor.h b/include/lldb/Utility/StringExtractor.h
index 40c1ef79cffb..311cec87e695 100644
--- a/include/lldb/Utility/StringExtractor.h
+++ b/include/lldb/Utility/StringExtractor.h
@@ -111,6 +111,8 @@ public:
size_t GetHexByteStringTerminatedBy(std::string &str, char terminator);
+ bool ConsumeFront(const llvm::StringRef &str);
+
const char *Peek() {
if (m_index < m_packet.size())
return m_packet.c_str() + m_index;
diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h
index ad10bbba1a57..f62b3cc0b19b 100644
--- a/include/lldb/lldb-enumerations.h
+++ b/include/lldb/lldb-enumerations.h
@@ -725,6 +725,18 @@ enum TraceType {
eTraceTypeProcessorTrace
};
+enum StructuredDataType {
+ eStructuredDataTypeInvalid = -1,
+ eStructuredDataTypeNull = 0,
+ eStructuredDataTypeGeneric,
+ eStructuredDataTypeArray,
+ eStructuredDataTypeInteger,
+ eStructuredDataTypeFloat,
+ eStructuredDataTypeBoolean,
+ eStructuredDataTypeString,
+ eStructuredDataTypeDictionary
+};
+
FLAGS_ENUM(TypeClass){
eTypeClassInvalid = (0u), eTypeClassArray = (1u << 0),
eTypeClassBlockPointer = (1u << 1), eTypeClassBuiltin = (1u << 2),
diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py
index bfd6f4642c6c..9cc585b75aa1 100644
--- a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py
+++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py
@@ -18,15 +18,9 @@ from lldbsuite.test import lldbutil
class UnwindFromExpressionTest(TestBase):
mydir = TestBase.compute_mydir(__file__)
+ main_spec = lldb.SBFileSpec("main.cpp", False)
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
-
- @add_test_categories(['pyapi'])
- @expectedFailureAll(oslist=["windows"])
- def test_unwind_expression(self):
- """Test unwinding from an expression."""
+ def build_and_run_to_bkpt(self):
self.build()
exe = os.path.join(os.getcwd(), "a.out")
@@ -35,9 +29,8 @@ class UnwindFromExpressionTest(TestBase):
self.assertTrue(target, VALID_TARGET)
# Create the breakpoint.
- main_spec = lldb.SBFileSpec("main.cpp", False)
breakpoint = target.BreakpointCreateBySourceRegex(
- "// Set a breakpoint here to get started", main_spec)
+ "// Set a breakpoint here to get started", self.main_spec)
self.assertTrue(breakpoint, VALID_BREAKPOINT)
# Launch the process, and do not stop at the entry point.
@@ -52,24 +45,60 @@ class UnwindFromExpressionTest(TestBase):
"instead the actual state is: '%s'" %
lldbutil.state_type_to_str(process.GetState()))
- thread = lldbutil.get_one_thread_stopped_at_breakpoint(
+ self.thread = lldbutil.get_one_thread_stopped_at_breakpoint(
process, breakpoint)
self.assertIsNotNone(
- thread, "Expected one thread to be stopped at the breakpoint")
+ self.thread, "Expected one thread to be stopped at the breakpoint")
+
+ # Next set a breakpoint in this function, set up Expression options to stop on
+ # breakpoint hits, and call the function.
+ self.fun_bkpt = self.target().BreakpointCreateBySourceRegex(
+ "// Stop inside the function here.", self.main_spec)
+ self.assertTrue(self.fun_bkpt, VALID_BREAKPOINT)
+
+
+ @no_debug_info_test
+ @expectedFailureAll(bugnumber="llvm.org/pr33164")
+ def test_conditional_bktp(self):
+ """
+ Test conditional breakpoint handling in the IgnoreBreakpoints = False case
+ """
+ self.build_and_run_to_bkpt()
+
+ self.fun_bkpt.SetCondition("0") # Should not get hit
+ options = lldb.SBExpressionOptions()
+ options.SetIgnoreBreakpoints(False)
+ options.SetUnwindOnError(False)
+
+ main_frame = self.thread.GetFrameAtIndex(0)
+ val = main_frame.EvaluateExpression("second_function(47)", options)
+ self.assertTrue(
+ val.GetError().Success(),
+ "We did complete the execution.")
+ self.assertEquals(47, val.GetValueAsSigned())
+
+ @add_test_categories(['pyapi'])
+ @expectedFailureAll(oslist=["windows"])
+ def test_unwind_expression(self):
+ """Test unwinding from an expression."""
+ self.build_and_run_to_bkpt()
+
+ # Run test with varying one thread timeouts to also test the halting
+ # logic in the IgnoreBreakpoints = False case
+ self.do_unwind_test(self.thread, self.fun_bkpt, 1000)
+ self.do_unwind_test(self.thread, self.fun_bkpt, 100000)
+
+ def do_unwind_test(self, thread, bkpt, timeout):
#
# Use Python API to evaluate expressions while stopped in a stack frame.
#
main_frame = thread.GetFrameAtIndex(0)
- # Next set a breakpoint in this function, set up Expression options to stop on
- # breakpoint hits, and call the function.
- fun_bkpt = target.BreakpointCreateBySourceRegex(
- "// Stop inside the function here.", main_spec)
- self.assertTrue(fun_bkpt, VALID_BREAKPOINT)
options = lldb.SBExpressionOptions()
options.SetIgnoreBreakpoints(False)
options.SetUnwindOnError(False)
+ options.SetOneThreadTimeoutInMicroSeconds(timeout)
val = main_frame.EvaluateExpression("a_function_to_call()", options)
@@ -82,7 +111,7 @@ class UnwindFromExpressionTest(TestBase):
"And the reason was right.")
thread = lldbutil.get_one_thread_stopped_at_breakpoint(
- process, fun_bkpt)
+ self.process(), bkpt)
self.assertTrue(
thread.IsValid(),
"We are indeed stopped at our breakpoint")
diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp b/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp
index e93c34a30b03..56b06f31ecca 100644
--- a/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp
+++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/main.cpp
@@ -7,8 +7,16 @@ a_function_to_call()
return static_value;
}
+int second_function(int x){
+ for(int i=0; i<10; ++i) {
+ a_function_to_call();
+ }
+ return x;
+}
+
int main (int argc, char const *argv[])
{
a_function_to_call(); // Set a breakpoint here to get started
+ second_function(1);
return 0;
}
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/Makefile b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile
index 644e2971a2c1..67aa16625bff 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/Makefile
+++ b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/Makefile
@@ -1,4 +1,4 @@
-LEVEL = ../../make
+LEVEL = ../../../make
CXX_SOURCES := main.cpp
ENABLE_THREADS := YES
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/TestNumThreads.py b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
index 094c86705969..094c86705969 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/TestNumThreads.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp
index 6a0ea4e0d119..6a0ea4e0d119 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/main.cpp
diff --git a/packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py b/packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py
new file mode 100644
index 000000000000..f19d01d5e695
--- /dev/null
+++ b/packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py
@@ -0,0 +1,206 @@
+"""
+Test some SBStructuredData API.
+"""
+
+from __future__ import print_function
+
+import os
+import re
+import time
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestStructuredDataAPI(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test(self):
+ self.structured_data_api_test()
+
+ def setUp(self):
+ TestBase.setUp(self)
+
+ @add_test_categories(['pyapi'])
+ def structured_data_api_test(self):
+ error = lldb.SBError()
+ s = lldb.SBStream()
+ s.Print(
+ "{\"key_dict\":{\"key_string\":\"STRING\",\"key_int\":3,\"key_float\":2.99,\"key_bool\":true,\"key_array\":[\"23\",\"arr\"]}}")
+ example = lldb.SBStructuredData()
+
+ # Check SetFromJSON API for dictionaries, integers, floating point
+ # values, strings and arrays
+ error = example.SetFromJSON(s)
+ if not error.Success():
+ self.fail("FAILED: " + error.GetCString())
+
+ # Tests for invalid data type
+ self.invalid_struct_test(example)
+
+ dict_struct = lldb.SBStructuredData()
+ dict_struct = example.GetValueForKey("key_dict")
+
+ # Tests for dictionary data type
+ self.dictionary_struct_test(example)
+
+ # Tests for string data type
+ self.string_struct_test(dict_struct)
+
+ # Tests for integer data type
+ self.int_struct_test(dict_struct)
+
+ # Tests for floating point data type
+ self.double_struct_test(dict_struct)
+
+ # Tests for boolean data type
+ self.bool_struct_test(dict_struct)
+
+ # Tests for array data type
+ self.array_struct_test(dict_struct)
+
+ def invalid_struct_test(self, example):
+ invalid_struct = lldb.SBStructuredData()
+ invalid_struct = example.GetValueForKey("invalid_key")
+ if invalid_struct.IsValid():
+ self.fail("An invalid object should have been returned")
+
+ # Check Type API
+ if not invalid_struct.GetType() == lldb.eStructuredDataTypeInvalid:
+ self.fail("Wrong type returned: " + str(invalid_struct.GetType()))
+
+ def dictionary_struct_test(self, example):
+ # Check API returning a valid SBStructuredData of 'dictionary' type
+ dict_struct = lldb.SBStructuredData()
+ dict_struct = example.GetValueForKey("key_dict")
+ if not dict_struct.IsValid():
+ self.fail("A valid object should have been returned")
+
+ # Check Type API
+ if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary:
+ self.fail("Wrong type returned: " + str(dict_struct.GetType()))
+
+ # Check Size API for 'dictionary' type
+ if not dict_struct.GetSize() == 5:
+ self.fail("Wrong no of elements returned: " +
+ str(dict_struct.GetSize()))
+
+ def string_struct_test(self, dict_struct):
+ string_struct = lldb.SBStructuredData()
+ string_struct = dict_struct.GetValueForKey("key_string")
+ if not string_struct.IsValid():
+ self.fail("A valid object should have been returned")
+
+ # Check Type API
+ if not string_struct.GetType() == lldb.eStructuredDataTypeString:
+ self.fail("Wrong type returned: " + str(string_struct.GetType()))
+
+ # Check API returning 'string' value
+ output = string_struct.GetStringValue(25)
+ if not "STRING" in output:
+ self.fail("wrong output: " + output)
+
+ # Calling wrong API on a SBStructuredData
+ # (e.g. getting an integer from a string type structure)
+ output = string_struct.GetIntegerValue()
+ if output:
+ self.fail(
+ "Valid integer value " +
+ str(output) +
+ " returned for a string object")
+
+ def int_struct_test(self, dict_struct):
+ # Check a valid SBStructuredData containing an 'integer' by
+ int_struct = lldb.SBStructuredData()
+ int_struct = dict_struct.GetValueForKey("key_int")
+ if not int_struct.IsValid():
+ self.fail("A valid object should have been returned")
+
+ # Check Type API
+ if not int_struct.GetType() == lldb.eStructuredDataTypeInteger:
+ self.fail("Wrong type returned: " + str(int_struct.GetType()))
+
+ # Check API returning 'integer' value
+ output = int_struct.GetIntegerValue()
+ if not output == 3:
+ self.fail("wrong output: " + str(output))
+
+ # Calling wrong API on a SBStructuredData
+ # (e.g. getting a string value from an integer type structure)
+ output = int_struct.GetStringValue(25)
+ if output:
+ self.fail(
+ "Valid string " +
+ output +
+ " returned for an integer object")
+
+ def double_struct_test(self, dict_struct):
+ floating_point_struct = lldb.SBStructuredData()
+ floating_point_struct = dict_struct.GetValueForKey("key_float")
+ if not floating_point_struct.IsValid():
+ self.fail("A valid object should have been returned")
+
+ # Check Type API
+ if not floating_point_struct.GetType() == lldb.eStructuredDataTypeFloat:
+ self.fail("Wrong type returned: " +
+ str(floating_point_struct.GetType()))
+
+ # Check API returning 'double' value
+ output = floating_point_struct.GetFloatValue()
+ if not output == 2.99:
+ self.fail("wrong output: " + str(output))
+
+ def bool_struct_test(self, dict_struct):
+ bool_struct = lldb.SBStructuredData()
+ bool_struct = dict_struct.GetValueForKey("key_bool")
+ if not bool_struct.IsValid():
+ self.fail("A valid object should have been returned")
+
+ # Check Type API
+ if not bool_struct.GetType() == lldb.eStructuredDataTypeBoolean:
+ self.fail("Wrong type returned: " + str(bool_struct.GetType()))
+
+ # Check API returning 'bool' value
+ output = bool_struct.GetBooleanValue()
+ if not output:
+ self.fail("wrong output: " + str(output))
+
+ def array_struct_test(self, dict_struct):
+ # Check API returning a valid SBStructuredData of 'array' type
+ array_struct = lldb.SBStructuredData()
+ array_struct = dict_struct.GetValueForKey("key_array")
+ if not array_struct.IsValid():
+ self.fail("A valid object should have been returned")
+
+ # Check Type API
+ if not array_struct.GetType() == lldb.eStructuredDataTypeArray:
+ self.fail("Wrong type returned: " + str(array_struct.GetType()))
+
+ # Check Size API for 'array' type
+ if not array_struct.GetSize() == 2:
+ self.fail("Wrong no of elements returned: " +
+ str(array_struct.GetSize()))
+
+ # Check API returning a valid SBStructuredData for different 'array'
+ # indices
+ string_struct = array_struct.GetItemAtIndex(0)
+ if not string_struct.IsValid():
+ self.fail("A valid object should have been returned")
+ if not string_struct.GetType() == lldb.eStructuredDataTypeString:
+ self.fail("Wrong type returned: " + str(string_struct.GetType()))
+ output = string_struct.GetStringValue(5)
+ if not output == "23":
+ self.fail("wrong output: " + str(output))
+
+ string_struct = array_struct.GetItemAtIndex(1)
+ if not string_struct.IsValid():
+ self.fail("A valid object should have been returned")
+ if not string_struct.GetType() == lldb.eStructuredDataTypeString:
+ self.fail("Wrong type returned: " + str(string_struct.GetType()))
+ output = string_struct.GetStringValue(5)
+ if not output == "arr":
+ self.fail("wrong output: " + str(output))
diff --git a/scripts/interface/SBStructuredData.i b/scripts/interface/SBStructuredData.i
index 1c55bacd31be..4e54cdd7b405 100644
--- a/scripts/interface/SBStructuredData.i
+++ b/scripts/interface/SBStructuredData.i
@@ -18,21 +18,38 @@ namespace lldb {
class SBStructuredData
{
public:
-
SBStructuredData();
-
+
SBStructuredData(const lldb::SBStructuredData &rhs);
SBStructuredData(const lldb::EventSP &event_sp);
~SBStructuredData();
-
+
bool
IsValid() const;
-
+
void
Clear();
+ lldb::SBStructuredData &operator=(const lldb::SBStructuredData &rhs);
+
+ lldb::StructuredDataType GetType() const;
+
+ size_t GetSize() const;
+
+ lldb::SBStructuredData GetValueForKey(const char *key) const;
+
+ lldb::SBStructuredData GetItemAtIndex(size_t idx) const;
+
+ uint64_t GetIntegerValue(uint64_t fail_value = 0) const;
+
+ double GetFloatValue(double fail_value = 0.0) const;
+
+ bool GetBooleanValue(bool fail_value = false) const;
+
+ size_t GetStringValue(char *dst, size_t dst_len) const;
+
lldb::SBError
GetAsJSON(lldb::SBStream &stream) const;
diff --git a/scripts/lldb.swig b/scripts/lldb.swig
index b0325e611d70..8f1b59c32d4d 100644
--- a/scripts/lldb.swig
+++ b/scripts/lldb.swig
@@ -31,8 +31,24 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions
and a source file location. SBCompileUnit contains SBLineEntry(s)."
%enddef
+/*
+Since version 3.0.9, swig's logic for importing the native module has changed in
+a way that is incompatible with our usage of the python module as __init__.py
+(See swig bug #769). Fortunately, since version 3.0.11, swig provides a way for
+us to override the module import logic to suit our needs. This does that.
+
+Older swig versions will simply ignore this setting.
+*/
+%define MODULEIMPORT
+"from . import $module"
+%enddef
+// These versions will not generate working python modules, so error out early.
+#if SWIG_VERSION >= 0x030009 && SWIG_VERSION < 0x030011
+#error Swig versions 3.0.9 and 3.0.10 are incompatible with lldb.
+#endif
+
// The name of the module to be created.
-%module(docstring=DOCSTRING) lldb
+%module(docstring=DOCSTRING, moduleimport=MODULEIMPORT) lldb
// Parameter types will be used in the autodoc string.
%feature("autodoc", "1");
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index 8b79e521a371..caf07dbe3ce8 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -363,10 +363,9 @@ lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options,
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
-
- uid = process_sp->StartTrace(options.m_traceoptions_sp, error.ref());
+ uid = process_sp->StartTrace(*(options.m_traceoptions_sp), error.ref());
trace_instance.SetTraceUID(uid);
- LLDB_LOG(log, "SBProcess::returned uid - %" PRIx64, uid);
+ LLDB_LOG(log, "SBProcess::returned uid - {0}", uid);
}
return trace_instance;
}
diff --git a/source/API/SBStructuredData.cpp b/source/API/SBStructuredData.cpp
index 971c4ab2295d..54022390b80f 100644
--- a/source/API/SBStructuredData.cpp
+++ b/source/API/SBStructuredData.cpp
@@ -46,7 +46,7 @@ lldb::SBError SBStructuredData::SetFromJSON(lldb::SBStream &stream) {
StructuredData::ObjectSP json_obj = StructuredData::ParseJSON(json_str);
m_impl_up->SetObjectSP(json_obj);
- if (!json_obj || json_obj->GetType() != StructuredData::Type::eTypeDictionary)
+ if (!json_obj || json_obj->GetType() != eStructuredDataTypeDictionary)
error.SetErrorString("Invalid Syntax");
return error;
}
@@ -67,3 +67,45 @@ lldb::SBError SBStructuredData::GetDescription(lldb::SBStream &stream) const {
sb_error.SetError(error);
return sb_error;
}
+
+StructuredDataType SBStructuredData::GetType() const {
+ return (m_impl_up ? m_impl_up->GetType() : eStructuredDataTypeInvalid);
+}
+
+size_t SBStructuredData::GetSize() const {
+ return (m_impl_up ? m_impl_up->GetSize() : 0);
+}
+
+lldb::SBStructuredData SBStructuredData::GetValueForKey(const char *key) const {
+ if (!m_impl_up)
+ return SBStructuredData();
+
+ SBStructuredData result;
+ result.m_impl_up->SetObjectSP(m_impl_up->GetValueForKey(key));
+ return result;
+}
+
+lldb::SBStructuredData SBStructuredData::GetItemAtIndex(size_t idx) const {
+ if (!m_impl_up)
+ return SBStructuredData();
+
+ SBStructuredData result;
+ result.m_impl_up->SetObjectSP(m_impl_up->GetItemAtIndex(idx));
+ return result;
+}
+
+uint64_t SBStructuredData::GetIntegerValue(uint64_t fail_value) const {
+ return (m_impl_up ? m_impl_up->GetIntegerValue(fail_value) : fail_value);
+}
+
+double SBStructuredData::GetFloatValue(double fail_value) const {
+ return (m_impl_up ? m_impl_up->GetFloatValue(fail_value) : fail_value);
+}
+
+bool SBStructuredData::GetBooleanValue(bool fail_value) const {
+ return (m_impl_up ? m_impl_up->GetBooleanValue(fail_value) : fail_value);
+}
+
+size_t SBStructuredData::GetStringValue(char *dst, size_t dst_len) const {
+ return (m_impl_up ? m_impl_up->GetStringValue(dst, dst_len) : 0);
+}
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index 2c82bc3bcdcf..65ccb465c8da 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -43,6 +43,7 @@
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBValue.h"
+#include "lldb/lldb-enumerations.h"
using namespace lldb;
using namespace lldb_private;
@@ -561,26 +562,26 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
StructuredData::ObjectSP node =
info_root_sp->GetObjectForDotSeparatedPath(path);
if (node) {
- if (node->GetType() == StructuredData::Type::eTypeString) {
+ if (node->GetType() == eStructuredDataTypeString) {
strm.Printf("%s", node->GetAsString()->GetValue().str().c_str());
success = true;
}
- if (node->GetType() == StructuredData::Type::eTypeInteger) {
+ if (node->GetType() == eStructuredDataTypeInteger) {
strm.Printf("0x%" PRIx64, node->GetAsInteger()->GetValue());
success = true;
}
- if (node->GetType() == StructuredData::Type::eTypeFloat) {
+ if (node->GetType() == eStructuredDataTypeFloat) {
strm.Printf("0x%f", node->GetAsFloat()->GetValue());
success = true;
}
- if (node->GetType() == StructuredData::Type::eTypeBoolean) {
+ if (node->GetType() == eStructuredDataTypeBoolean) {
if (node->GetAsBoolean()->GetValue() == true)
strm.Printf("true");
else
strm.Printf("false");
success = true;
}
- if (node->GetType() == StructuredData::Type::eTypeNull) {
+ if (node->GetType() == eStructuredDataTypeNull) {
strm.Printf("null");
success = true;
}
diff --git a/source/API/SBTrace.cpp b/source/API/SBTrace.cpp
index 18f7d36e7759..9a5fa4ed4f46 100644
--- a/source/API/SBTrace.cpp
+++ b/source/API/SBTrace.cpp
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Utility/Log.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/Log.h"
#include "lldb/API/SBTrace.h"
#include "lldb/API/SBTraceOptions.h"
@@ -25,37 +25,37 @@ lldb::ProcessSP SBTrace::GetSP() const { return m_opaque_wp.lock(); }
size_t SBTrace::GetTraceData(SBError &error, void *buf, size_t size,
size_t offset, lldb::tid_t thread_id) {
- size_t bytes_read = 0;
ProcessSP process_sp(GetSP());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
error.Clear();
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
- bytes_read = process_sp->GetData(GetTraceUID(), thread_id, error.ref(), buf,
- size, offset);
- LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read);
+ error.SetError(
+ process_sp->GetData(GetTraceUID(), thread_id, buffer, offset));
+ LLDB_LOG(log, "SBTrace::bytes_read - {0}", buffer.size());
}
- return bytes_read;
+ return buffer.size();
}
size_t SBTrace::GetMetaData(SBError &error, void *buf, size_t size,
size_t offset, lldb::tid_t thread_id) {
- size_t bytes_read = 0;
ProcessSP process_sp(GetSP());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
error.Clear();
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
- bytes_read = process_sp->GetMetaData(GetTraceUID(), thread_id, error.ref(),
- buf, size, offset);
- LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read);
+ error.SetError(
+ process_sp->GetMetaData(GetTraceUID(), thread_id, buffer, offset));
+ LLDB_LOG(log, "SBTrace::bytes_read - {0}", buffer.size());
}
- return bytes_read;
+ return buffer.size();
}
void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) {
@@ -66,7 +66,7 @@ void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) {
error.SetErrorString("invalid process");
return;
}
- process_sp->StopTrace(GetTraceUID(), thread_id, error.ref());
+ error.SetError(process_sp->StopTrace(GetTraceUID(), thread_id));
}
void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
@@ -76,8 +76,8 @@ void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
- process_sp->GetTraceConfig(GetTraceUID(), error.ref(),
- options.m_traceoptions_sp);
+ error.SetError(process_sp->GetTraceConfig(GetTraceUID(),
+ *(options.m_traceoptions_sp)));
}
}
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index 6b0f1b455bc1..b585ef9ef8ad 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -649,7 +649,7 @@ protected:
new_plan_sp->SetOkayToDiscard(false);
if (m_options.m_step_count > 1) {
- if (new_plan_sp->SetIterationCount(m_options.m_step_count)) {
+ if (!new_plan_sp->SetIterationCount(m_options.m_step_count)) {
result.AppendWarning(
"step operation does not support iteration count.");
}
diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp
index 9fb294aad2fb..e3c346f79d6b 100644
--- a/source/Core/FormatEntity.cpp
+++ b/source/Core/FormatEntity.cpp
@@ -1040,24 +1040,24 @@ static bool FormatThreadExtendedInfoRecurse(
thread_info_dictionary->GetObjectForDotSeparatedPath(path);
if (value) {
- if (value->GetType() == StructuredData::Type::eTypeInteger) {
+ if (value->GetType() == eStructuredDataTypeInteger) {
const char *token_format = "0x%4.4" PRIx64;
if (!entry.printf_format.empty())
token_format = entry.printf_format.c_str();
s.Printf(token_format, value->GetAsInteger()->GetValue());
return true;
- } else if (value->GetType() == StructuredData::Type::eTypeFloat) {
+ } else if (value->GetType() == eStructuredDataTypeFloat) {
s.Printf("%f", value->GetAsFloat()->GetValue());
return true;
- } else if (value->GetType() == StructuredData::Type::eTypeString) {
+ } else if (value->GetType() == eStructuredDataTypeString) {
s.Format("{0}", value->GetAsString()->GetValue());
return true;
- } else if (value->GetType() == StructuredData::Type::eTypeArray) {
+ } else if (value->GetType() == eStructuredDataTypeArray) {
if (value->GetAsArray()->GetSize() > 0) {
s.Printf("%zu", value->GetAsArray()->GetSize());
return true;
}
- } else if (value->GetType() == StructuredData::Type::eTypeDictionary) {
+ } else if (value->GetType() == eStructuredDataTypeDictionary) {
s.Printf("%zu",
value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize());
return true;
@@ -1346,7 +1346,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
if (thread) {
StructuredData::ObjectSP object_sp = thread->GetExtendedInfo();
if (object_sp &&
- object_sp->GetType() == StructuredData::Type::eTypeDictionary) {
+ object_sp->GetType() == eStructuredDataTypeDictionary) {
if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s))
return true;
}
diff --git a/source/Core/StructuredData.cpp b/source/Core/StructuredData.cpp
index d52b7730cc65..b03665ed3485 100644
--- a/source/Core/StructuredData.cpp
+++ b/source/Core/StructuredData.cpp
@@ -184,7 +184,7 @@ StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) {
StructuredData::ObjectSP
StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
- if (this->GetType() == Type::eTypeDictionary) {
+ if (this->GetType() == lldb::eStructuredDataTypeDictionary) {
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
std::string key = match.first.str();
ObjectSP value = this->GetAsDictionary()->GetValueForKey(key);
@@ -200,7 +200,7 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
return ObjectSP();
}
- if (this->GetType() == Type::eTypeArray) {
+ if (this->GetType() == lldb::eStructuredDataTypeArray) {
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
if (match.second.size() == 0) {
return this->shared_from_this();
diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp
index 7d4b398a171d..7b580dde656a 100644
--- a/source/Host/common/Editline.cpp
+++ b/source/Host/common/Editline.cpp
@@ -474,7 +474,7 @@ unsigned char Editline::RecallHistory(bool earlier) {
return CC_NEWLINE;
}
-int Editline::GetCharacter(EditLineCharType *c) {
+int Editline::GetCharacter(EditLineGetCharType *c) {
const LineInfoW *info = el_wline(m_editline);
// Paint a faint version of the desired prompt over the version libedit draws
@@ -969,7 +969,7 @@ void Editline::ConfigureEditor(bool multiline) {
}));
el_wset(m_editline, EL_GETCFN, (EditlineGetCharCallbackType)([](
- EditLine *editline, EditLineCharType *c) {
+ EditLine *editline, EditLineGetCharType *c) {
return Editline::InstanceFor(editline)->GetCharacter(c);
}));
@@ -1360,12 +1360,12 @@ void Editline::PrintAsync(Stream *stream, const char *s, size_t len) {
}
}
-bool Editline::CompleteCharacter(char ch, EditLineCharType &out) {
+bool Editline::CompleteCharacter(char ch, EditLineGetCharType &out) {
#if !LLDB_EDITLINE_USE_WCHAR
if (ch == (char)EOF)
return false;
- out = ch;
+ out = (unsigned char)ch;
return true;
#else
std::codecvt_utf8<wchar_t> cvt;
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
index 3ceda5ff67e9..439d372fadeb 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
@@ -254,11 +254,12 @@ bool fixupRSAllocationStructByValCalls(llvm::Module &module) {
llvm::AttributeList call_attribs = call_inst->getAttributes();
// iterate over the argument attributes
- for (size_t i = 1; i <= call_attribs.getNumSlots(); ++i) {
+ for (unsigned I = call_attribs.index_begin(); I != call_attribs.index_end();
+ I++) {
// if this argument is passed by val
- if (call_attribs.hasAttribute(i, llvm::Attribute::ByVal)) {
+ if (call_attribs.hasAttribute(I, llvm::Attribute::ByVal)) {
// strip away the byval attribute
- call_inst->removeAttribute(i, llvm::Attribute::ByVal);
+ call_inst->removeAttribute(I, llvm::Attribute::ByVal);
changed = true;
}
}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 1667490f1344..34d99cd39de2 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -1132,6 +1132,10 @@ ProcessMessage ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
case 0:
case TRAP_TRACE:
+#ifdef TRAP_CAP
+ // Map TRAP_CAP to a trace trap in the absense of a more specific handler.
+ case TRAP_CAP:
+#endif
if (log)
log->Printf("ProcessMonitor::%s() received trace event, tid = %" PRIu64
" : si_code = %d",
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 80751147b4f5..efb19fc414f9 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -167,8 +167,6 @@ NativeProcessNetBSD::NativeProcessNetBSD()
// Handles all waitpid events from the inferior process.
void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
switch (signal) {
case SIGTRAP:
return MonitorSIGTRAP(pid);
@@ -196,7 +194,6 @@ void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, int signal,
}
void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
ptrace_siginfo_t info;
const auto siginfo_err =
@@ -305,8 +302,6 @@ void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
}
void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
-
ptrace_siginfo_t info;
const auto siginfo_err =
PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
@@ -898,6 +893,19 @@ void NativeProcessNetBSD::SigchldHandler() {
MonitorCallback(wait_pid, signal);
}
+bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
+ for (auto thread_sp : m_threads) {
+ assert(thread_sp && "thread list should not contain NULL threads");
+ if (thread_sp->GetID() == thread_id) {
+ // We have this thread.
+ return true;
+ }
+ }
+
+ // We don't have this thread.
+ return false;
+}
+
NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
@@ -916,8 +924,6 @@ NativeThreadNetBSDSP NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
}
::pid_t NativeProcessNetBSD::Attach(lldb::pid_t pid, Status &error) {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
if (pid <= 1) {
error.SetErrorToGenericError();
error.SetErrorString("Attaching to process 1 is not allowed.");
@@ -1006,7 +1012,7 @@ Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
io.piod_len = size;
do {
- io.piod_addr = (void *)(src + bytes_written);
+ io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
io.piod_offs = (void *)(addr + bytes_written);
Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
@@ -1034,10 +1040,11 @@ NativeProcessNetBSD::GetAuxvData() const {
ErrorOr<std::unique_ptr<MemoryBuffer>> buf =
llvm::MemoryBuffer::getNewMemBuffer(auxv_size);
- struct ptrace_io_desc io = {.piod_op = PIOD_READ_AUXV,
- .piod_offs = 0,
- .piod_addr = (void *)buf.get()->getBufferStart(),
- .piod_len = auxv_size};
+ struct ptrace_io_desc io;
+ io.piod_op = PIOD_READ_AUXV;
+ io.piod_offs = 0;
+ io.piod_addr = const_cast<void *>(static_cast<const void *>(buf.get()->getBufferStart()));
+ io.piod_len = auxv_size;
Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index e18ba162e523..758956e3dca1 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -115,6 +115,8 @@ private:
// ---------------------------------------------------------------------
NativeProcessNetBSD();
+ bool HasThreadNoLock(lldb::tid_t thread_id);
+
NativeThreadNetBSDSP AddThread(lldb::tid_t thread_id);
Status LaunchInferior(MainLoop &mainloop, ProcessLaunchInfo &launch_info);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 550ec0ea499a..33aed7a43c4a 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -30,7 +30,6 @@
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/StreamGDBRemote.h"
#include "lldb/Utility/StreamString.h"
// Project includes
@@ -3152,6 +3151,211 @@ bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) {
response.IsOKResponse();
}
+lldb::user_id_t
+GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options,
+ Status &error) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ lldb::user_id_t ret_uid = LLDB_INVALID_UID;
+
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jTraceStart:");
+
+ StructuredData::Dictionary json_packet;
+ json_packet.AddIntegerItem("type", options.getType());
+ json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
+ json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
+
+ if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
+ json_packet.AddIntegerItem("threadid", options.getThreadID());
+
+ StructuredData::DictionarySP custom_params = options.getTraceParams();
+ if (custom_params)
+ json_packet.AddItem("params", custom_params);
+
+ StreamString json_string;
+ json_packet.Dump(json_string, false);
+ escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (!response.IsNormalResponse()) {
+ error.SetError(response.GetError(), eErrorTypeGeneric);
+ LLDB_LOG(log, "Target does not support Tracing");
+ } else {
+ ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID);
+ }
+ } else {
+ LLDB_LOG(log, "failed to send packet");
+ error.SetErrorStringWithFormat("failed to send packet: '%s'",
+ escaped_packet.GetData());
+ }
+ return ret_uid;
+}
+
+Status
+GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid,
+ lldb::tid_t thread_id) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ StringExtractorGDBRemote response;
+ Status error;
+
+ StructuredData::Dictionary json_packet;
+ StreamGDBRemote escaped_packet;
+ StreamString json_string;
+ escaped_packet.PutCString("jTraceStop:");
+
+ json_packet.AddIntegerItem("traceid", uid);
+
+ if (thread_id != LLDB_INVALID_THREAD_ID)
+ json_packet.AddIntegerItem("threadid", thread_id);
+
+ json_packet.Dump(json_string, false);
+
+ escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (!response.IsOKResponse()) {
+ error.SetError(response.GetError(), eErrorTypeGeneric);
+ LLDB_LOG(log, "stop tracing failed");
+ }
+ } else {
+ LLDB_LOG(log, "failed to send packet");
+ error.SetErrorStringWithFormat(
+ "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(),
+ response.GetError());
+ }
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::SendGetDataPacket(
+ lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jTraceBufferRead:");
+ return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
+}
+
+Status GDBRemoteCommunicationClient::SendGetMetaDataPacket(
+ lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jTraceMetaRead:");
+ return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
+}
+
+Status
+GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid,
+ TraceOptions &options) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ StringExtractorGDBRemote response;
+ Status error;
+
+ StreamString json_string;
+ StreamGDBRemote escaped_packet;
+ escaped_packet.PutCString("jTraceConfigRead:");
+
+ StructuredData::Dictionary json_packet;
+ json_packet.AddIntegerItem("traceid", uid);
+
+ if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
+ json_packet.AddIntegerItem("threadid", options.getThreadID());
+
+ json_packet.Dump(json_string, false);
+ escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+
+ if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ uint64_t type = std::numeric_limits<uint64_t>::max();
+ uint64_t buffersize = std::numeric_limits<uint64_t>::max();
+ uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
+
+ auto json_object = StructuredData::ParseJSON(response.Peek());
+
+ if (!json_object ||
+ json_object->GetType() != lldb::eStructuredDataTypeDictionary) {
+ error.SetErrorString("Invalid Configuration obtained");
+ return error;
+ }
+
+ auto json_dict = json_object->GetAsDictionary();
+
+ json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize",
+ metabuffersize);
+ options.setMetaDataBufferSize(metabuffersize);
+
+ json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize);
+ options.setTraceBufferSize(buffersize);
+
+ json_dict->GetValueForKeyAsInteger<uint64_t>("type", type);
+ options.setType(static_cast<lldb::TraceType>(type));
+
+ StructuredData::ObjectSP custom_params_sp =
+ json_dict->GetValueForKey("params");
+ if (custom_params_sp) {
+ if (custom_params_sp->GetType() !=
+ lldb::eStructuredDataTypeDictionary) {
+ error.SetErrorString("Invalid Configuration obtained");
+ return error;
+ } else
+ options.setTraceParams(
+ static_pointer_cast<StructuredData::Dictionary>(
+ custom_params_sp));
+ }
+ } else {
+ error.SetError(response.GetError(), eErrorTypeGeneric);
+ }
+ } else {
+ LLDB_LOG(log, "failed to send packet");
+ error.SetErrorStringWithFormat("failed to send packet: '%s'",
+ escaped_packet.GetData());
+ }
+ return error;
+}
+
+Status GDBRemoteCommunicationClient::SendGetTraceDataPacket(
+ StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Status error;
+
+ StructuredData::Dictionary json_packet;
+
+ json_packet.AddIntegerItem("traceid", uid);
+ json_packet.AddIntegerItem("offset", offset);
+ json_packet.AddIntegerItem("buffersize", buffer.size());
+
+ if (thread_id != LLDB_INVALID_THREAD_ID)
+ json_packet.AddIntegerItem("threadid", thread_id);
+
+ StreamString json_string;
+ json_packet.Dump(json_string, false);
+
+ packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ size_t filled_size = response.GetHexBytesAvail(buffer);
+ buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size);
+ } else {
+ error.SetError(response.GetError(), eErrorTypeGeneric);
+ buffer = buffer.slice(buffer.size());
+ }
+ } else {
+ LLDB_LOG(log, "failed to send packet");
+ error.SetErrorStringWithFormat("failed to send packet: '%s'",
+ packet.GetData());
+ buffer = buffer.slice(buffer.size());
+ }
+ return error;
+}
+
bool GDBRemoteCommunicationClient::GetModuleInfo(
const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
ModuleSpec &module_spec) {
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 08d0bd5d690b..6306651da7a1 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -25,6 +25,7 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/StreamGDBRemote.h"
#include "llvm/ADT/Optional.h"
@@ -499,6 +500,21 @@ public:
ConfigureRemoteStructuredData(const ConstString &type_name,
const StructuredData::ObjectSP &config_sp);
+ lldb::user_id_t SendStartTracePacket(const TraceOptions &options,
+ Status &error);
+
+ Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id);
+
+ Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0);
+
+ Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0);
+
+ Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options);
+
protected:
LazyBool m_supports_not_sending_acks;
LazyBool m_supports_thread_suffix;
@@ -587,6 +603,11 @@ protected:
lldb::tid_t tid, StreamString &&payload,
StringExtractorGDBRemote &response, bool send_async);
+ Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid,
+ lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset);
+
private:
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index ec7c2f5330d7..d318c35366f1 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -183,6 +183,22 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
StringExtractorGDBRemote::eServerPacketType_QPassSignals,
&GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jTraceStart,
+ &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead,
+ &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead,
+ &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jTraceStop,
+ &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
+ &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
+
RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
[this](StringExtractorGDBRemote packet, Status &error,
bool &interrupt, bool &quit) {
@@ -1084,6 +1100,231 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
}
GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceStart(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
+
+ if (!packet.ConsumeFront("jTraceStart:"))
+ return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
+
+ TraceOptions options;
+ uint64_t type = std::numeric_limits<uint64_t>::max();
+ uint64_t buffersize = std::numeric_limits<uint64_t>::max();
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
+
+ auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+ if (!json_object ||
+ json_object->GetType() != lldb::eStructuredDataTypeDictionary)
+ return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
+
+ auto json_dict = json_object->GetAsDictionary();
+
+ json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize);
+ options.setMetaDataBufferSize(metabuffersize);
+
+ json_dict->GetValueForKeyAsInteger("buffersize", buffersize);
+ options.setTraceBufferSize(buffersize);
+
+ json_dict->GetValueForKeyAsInteger("type", type);
+ options.setType(static_cast<lldb::TraceType>(type));
+
+ json_dict->GetValueForKeyAsInteger("threadid", tid);
+ options.setThreadID(tid);
+
+ StructuredData::ObjectSP custom_params_sp =
+ json_dict->GetValueForKey("params");
+ if (custom_params_sp &&
+ custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary)
+ return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
+
+ options.setTraceParams(
+ static_pointer_cast<StructuredData::Dictionary>(custom_params_sp));
+
+ if (buffersize == std::numeric_limits<uint64_t>::max() ||
+ type != lldb::TraceType::eTraceTypeProcessorTrace) {
+ LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize,
+ type);
+ return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet ");
+ }
+
+ Status error;
+ lldb::user_id_t uid = LLDB_INVALID_UID;
+ uid = m_debugged_process_sp->StartTrace(options, error);
+ LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError());
+ if (error.Fail())
+ return SendErrorResponse(error.GetError());
+
+ StreamGDBRemote response;
+ response.Printf("%" PRIx64, uid);
+ return SendPacketNoLock(response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceStop(
+ StringExtractorGDBRemote &packet) {
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
+
+ if (!packet.ConsumeFront("jTraceStop:"))
+ return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+
+ lldb::user_id_t uid = LLDB_INVALID_UID;
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+
+ auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+ if (!json_object ||
+ json_object->GetType() != lldb::eStructuredDataTypeDictionary)
+ return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+
+ auto json_dict = json_object->GetAsDictionary();
+
+ if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
+ return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+
+ json_dict->GetValueForKeyAsInteger("threadid", tid);
+
+ Status error = m_debugged_process_sp->StopTrace(uid, tid);
+
+ if (error.Fail())
+ return SendErrorResponse(error.GetError());
+
+ return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead(
+ StringExtractorGDBRemote &packet) {
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
+
+ if (!packet.ConsumeFront("jTraceConfigRead:"))
+ return SendIllFormedResponse(packet,
+ "jTraceConfigRead: Ill formed packet ");
+
+ lldb::user_id_t uid = LLDB_INVALID_UID;
+ lldb::tid_t threadid = LLDB_INVALID_THREAD_ID;
+
+ auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+ if (!json_object ||
+ json_object->GetType() != lldb::eStructuredDataTypeDictionary)
+ return SendIllFormedResponse(packet,
+ "jTraceConfigRead: Ill formed packet ");
+
+ auto json_dict = json_object->GetAsDictionary();
+
+ if (!json_dict->GetValueForKeyAsInteger("traceid", uid))
+ return SendIllFormedResponse(packet,
+ "jTraceConfigRead: Ill formed packet ");
+
+ json_dict->GetValueForKeyAsInteger("threadid", threadid);
+
+ TraceOptions options;
+ StreamGDBRemote response;
+
+ options.setThreadID(threadid);
+ Status error = m_debugged_process_sp->GetTraceConfig(uid, options);
+
+ if (error.Fail())
+ return SendErrorResponse(error.GetError());
+
+ StreamGDBRemote escaped_response;
+ StructuredData::Dictionary json_packet;
+
+ json_packet.AddIntegerItem("type", options.getType());
+ json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
+ json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
+
+ StructuredData::DictionarySP custom_params = options.getTraceParams();
+ if (custom_params)
+ json_packet.AddItem("params", custom_params);
+
+ StreamString json_string;
+ json_packet.Dump(json_string, false);
+ escaped_response.PutEscapedBytes(json_string.GetData(),
+ json_string.GetSize());
+ return SendPacketNoLock(escaped_response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceRead(
+ StringExtractorGDBRemote &packet) {
+
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
+
+ enum PacketType { MetaData, BufferData };
+ PacketType tracetype = MetaData;
+
+ if (packet.ConsumeFront("jTraceBufferRead:"))
+ tracetype = BufferData;
+ else if (packet.ConsumeFront("jTraceMetaRead:"))
+ tracetype = MetaData;
+ else {
+ return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
+ }
+
+ lldb::user_id_t uid = LLDB_INVALID_UID;
+
+ size_t byte_count = std::numeric_limits<size_t>::max();
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ size_t offset = std::numeric_limits<size_t>::max();
+
+ auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+ if (!json_object ||
+ json_object->GetType() != lldb::eStructuredDataTypeDictionary)
+ return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
+
+ auto json_dict = json_object->GetAsDictionary();
+
+ if (!json_dict->GetValueForKeyAsInteger("traceid", uid) ||
+ !json_dict->GetValueForKeyAsInteger("offset", offset) ||
+ !json_dict->GetValueForKeyAsInteger("buffersize", byte_count))
+ return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
+
+ json_dict->GetValueForKeyAsInteger("threadid", tid);
+
+ // Allocate the response buffer.
+ std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]);
+ if (!buffer)
+ return SendErrorResponse(0x78);
+
+ StreamGDBRemote response;
+ Status error;
+ llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count);
+
+ if (tracetype == BufferData)
+ error = m_debugged_process_sp->GetData(uid, tid, buf, offset);
+ else if (tracetype == MetaData)
+ error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset);
+
+ if (error.Fail())
+ return SendErrorResponse(error.GetError());
+
+ for (size_t i = 0; i < buf.size(); ++i)
+ response.PutHex8(buf[i]);
+
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
+ return SendPacketNoLock(escaped_response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
StringExtractorGDBRemote &packet) {
// Fail if we don't have a current process.
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index ebda9a911d3c..a7d7850d454f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -189,6 +189,14 @@ protected:
PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet);
+
+ PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet);
+
PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet);
PacketResult Handle_vAttach(StringExtractorGDBRemote &packet);
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 64684c5963b3..aeb7c742b4f4 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1236,6 +1236,32 @@ Status ProcessGDBRemote::DoAttachToProcessWithName(
return error;
}
+lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options,
+ Status &error) {
+ return m_gdb_comm.SendStartTracePacket(options, error);
+}
+
+Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
+ return m_gdb_comm.SendStopTracePacket(uid, thread_id);
+}
+
+Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset) {
+ return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset);
+}
+
+Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset) {
+ return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset);
+}
+
+Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid,
+ TraceOptions &options) {
+ return m_gdb_comm.SendGetTraceConfigPacket(uid, options);
+}
+
void ProcessGDBRemote::DidExit() {
// When we exit, disconnect from the GDB server communications
m_gdb_comm.Disconnect();
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 60f0464f86bb..d7a4e961b540 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -31,6 +31,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
+#include "lldb/Utility/StreamGDBRemote.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringExtractor.h"
#include "lldb/Utility/StringList.h"
@@ -177,6 +178,21 @@ public:
Status GetWatchpointSupportInfo(uint32_t &num) override;
+ lldb::user_id_t StartTrace(const TraceOptions &options,
+ Status &error) override;
+
+ Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) override;
+
+ Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0) override;
+
+ Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
+ llvm::MutableArrayRef<uint8_t> &buffer,
+ size_t offset = 0) override;
+
+ Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override;
+
Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
bool StartNoticingNewThreads() override;
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index ff86b0dbe051..c6ad536cee10 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -4823,6 +4823,48 @@ GetExpressionTimeout(const EvaluateExpressionOptions &options,
return *options.GetTimeout() - GetOneThreadExpressionTimeout(options);
}
+static llvm::Optional<ExpressionResults>
+HandleStoppedEvent(Thread &thread, const ThreadPlanSP &thread_plan_sp,
+ RestorePlanState &restorer, const EventSP &event_sp,
+ EventSP &event_to_broadcast_sp,
+ const EvaluateExpressionOptions &options, bool handle_interrupts) {
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STEP | LIBLLDB_LOG_PROCESS);
+
+ ThreadPlanSP plan = thread.GetCompletedPlan();
+ if (plan == thread_plan_sp && plan->PlanSucceeded()) {
+ LLDB_LOG(log, "execution completed successfully");
+
+ // Restore the plan state so it will get reported as intended when we are
+ // done.
+ restorer.Clean();
+ return eExpressionCompleted;
+ }
+
+ StopInfoSP stop_info_sp = thread.GetStopInfo();
+ if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint &&
+ stop_info_sp->ShouldNotify(event_sp.get())) {
+ LLDB_LOG(log, "stopped for breakpoint: {0}.", stop_info_sp->GetDescription());
+ if (!options.DoesIgnoreBreakpoints()) {
+ // Restore the plan state and then force Private to false. We are going
+ // to stop because of this plan so we need it to become a public plan or
+ // it won't report correctly when we continue to its termination later on.
+ restorer.Clean();
+ thread_plan_sp->SetPrivate(false);
+ event_to_broadcast_sp = event_sp;
+ }
+ return eExpressionHitBreakpoint;
+ }
+
+ if (!handle_interrupts &&
+ Process::ProcessEventData::GetInterruptedFromEvent(event_sp.get()))
+ return llvm::None;
+
+ LLDB_LOG(log, "thread plan did not successfully complete");
+ if (!options.DoesUnwindOnError())
+ event_to_broadcast_sp = event_sp;
+ return eExpressionInterrupted;
+}
+
ExpressionResults
Process::RunThreadPlan(ExecutionContext &exe_ctx,
lldb::ThreadPlanSP &thread_plan_sp,
@@ -5228,65 +5270,22 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
"but our thread (index-id=%u) has vanished.",
thread_idx_id);
return_value = eExpressionInterrupted;
- } else {
+ } else if (Process::ProcessEventData::GetRestartedFromEvent(
+ event_sp.get())) {
// If we were restarted, we just need to go back up to fetch
// another event.
- if (Process::ProcessEventData::GetRestartedFromEvent(
- event_sp.get())) {
- if (log) {
- log->Printf("Process::RunThreadPlan(): Got a stop and "
- "restart, so we'll continue waiting.");
- }
- keep_going = true;
- do_resume = false;
- handle_running_event = true;
- } else {
- ThreadPlanSP plan = thread->GetCompletedPlan();
- if (plan == thread_plan_sp && plan->PlanSucceeded()) {
-
- if (log)
- log->PutCString("Process::RunThreadPlan(): execution "
- "completed successfully.");
-
- // Restore the plan state so it will get reported as
- // intended when we are done.
- thread_plan_restorer.Clean();
-
- return_value = eExpressionCompleted;
- } else {
- StopInfoSP stop_info_sp = thread_sp->GetStopInfo();
- // Something restarted the target, so just wait for it to
- // stop for real.
- if (stop_info_sp &&
- stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
- if (log)
- log->Printf("Process::RunThreadPlan() stopped for "
- "breakpoint: %s.",
- stop_info_sp->GetDescription());
- return_value = eExpressionHitBreakpoint;
- if (!options.DoesIgnoreBreakpoints()) {
- // Restore the plan state and then force Private to
- // false. We are
- // going to stop because of this plan so we need it to
- // become a public
- // plan or it won't report correctly when we continue to
- // its termination
- // later on.
- thread_plan_restorer.Clean();
- if (thread_plan_sp)
- thread_plan_sp->SetPrivate(false);
- event_to_broadcast_sp = event_sp;
- }
- } else {
- if (log)
- log->PutCString("Process::RunThreadPlan(): thread plan "
- "didn't successfully complete.");
- if (!options.DoesUnwindOnError())
- event_to_broadcast_sp = event_sp;
- return_value = eExpressionInterrupted;
- }
- }
+ if (log) {
+ log->Printf("Process::RunThreadPlan(): Got a stop and "
+ "restart, so we'll continue waiting.");
}
+ keep_going = true;
+ do_resume = false;
+ handle_running_event = true;
+ } else {
+ const bool handle_interrupts = true;
+ return_value = *HandleStoppedEvent(
+ *thread, thread_plan_sp, thread_plan_restorer, event_sp,
+ event_to_broadcast_sp, options, handle_interrupts);
}
} break;
@@ -5392,20 +5391,6 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
}
if (stop_state == lldb::eStateStopped) {
- // Between the time we initiated the Halt and the time we
- // delivered it, the process could have
- // already finished its job. Check that here:
-
- if (thread->IsThreadPlanDone(thread_plan_sp.get())) {
- if (log)
- log->PutCString("Process::RunThreadPlan(): Even though we "
- "timed out, the call plan was done. "
- "Exiting wait loop.");
- return_value = eExpressionCompleted;
- back_to_top = false;
- break;
- }
-
if (Process::ProcessEventData::GetRestartedFromEvent(
event_sp.get())) {
if (log)
@@ -5419,6 +5404,18 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
continue;
}
+ // Between the time we initiated the Halt and the time we
+ // delivered it, the process could have
+ // already finished its job. Check that here:
+ const bool handle_interrupts = false;
+ if (auto result = HandleStoppedEvent(
+ *thread, thread_plan_sp, thread_plan_restorer, event_sp,
+ event_to_broadcast_sp, options, handle_interrupts)) {
+ return_value = *result;
+ back_to_top = false;
+ break;
+ }
+
if (!options.GetTryAllThreads()) {
if (log)
log->PutCString("Process::RunThreadPlan(): try_all_threads "
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 43ae7b5413be..4aba30be5f78 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -51,6 +51,7 @@
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-enumerations.h"
using namespace lldb;
using namespace lldb_private;
@@ -397,7 +398,7 @@ lldb::StopInfoSP Thread::GetStopInfo() {
bool plan_overrides_trace =
have_valid_stop_info && have_valid_completed_plan
&& (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
-
+
if (have_valid_stop_info && !plan_overrides_trace) {
return m_stop_info_sp;
} else if (have_valid_completed_plan) {
@@ -541,7 +542,7 @@ bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) {
saved_state.orig_stop_id = process_sp->GetStopID();
saved_state.current_inlined_depth = GetCurrentInlinedDepth();
saved_state.m_completed_plan_stack = m_completed_plan_stack;
-
+
return true;
}
@@ -1994,13 +1995,12 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
thread_info->GetObjectForDotSeparatedPath("trace_messages");
bool printed_activity = false;
- if (activity &&
- activity->GetType() == StructuredData::Type::eTypeDictionary) {
+ if (activity && activity->GetType() == eStructuredDataTypeDictionary) {
StructuredData::Dictionary *activity_dict = activity->GetAsDictionary();
StructuredData::ObjectSP id = activity_dict->GetValueForKey("id");
StructuredData::ObjectSP name = activity_dict->GetValueForKey("name");
- if (name && name->GetType() == StructuredData::Type::eTypeString && id &&
- id->GetType() == StructuredData::Type::eTypeInteger) {
+ if (name && name->GetType() == eStructuredDataTypeString && id &&
+ id->GetType() == eStructuredDataTypeInteger) {
strm.Format(" Activity '{0}', {1:x}\n",
name->GetAsString()->GetValue(),
id->GetAsInteger()->GetValue());
@@ -2008,8 +2008,7 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
printed_activity = true;
}
bool printed_breadcrumb = false;
- if (breadcrumb &&
- breadcrumb->GetType() == StructuredData::Type::eTypeDictionary) {
+ if (breadcrumb && breadcrumb->GetType() == eStructuredDataTypeDictionary) {
if (printed_activity)
strm.Printf("\n");
StructuredData::Dictionary *breadcrumb_dict =
@@ -2017,13 +2016,13 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
StructuredData::ObjectSP breadcrumb_text =
breadcrumb_dict->GetValueForKey("name");
if (breadcrumb_text &&
- breadcrumb_text->GetType() == StructuredData::Type::eTypeString) {
+ breadcrumb_text->GetType() == eStructuredDataTypeString) {
strm.Format(" Current Breadcrumb: {0}\n",
breadcrumb_text->GetAsString()->GetValue());
}
printed_breadcrumb = true;
}
- if (messages && messages->GetType() == StructuredData::Type::eTypeArray) {
+ if (messages && messages->GetType() == eStructuredDataTypeArray) {
if (printed_breadcrumb)
strm.Printf("\n");
StructuredData::Array *messages_array = messages->GetAsArray();
@@ -2032,14 +2031,13 @@ bool Thread::GetDescription(Stream &strm, lldb::DescriptionLevel level,
strm.Printf(" %zu trace messages:\n", msg_count);
for (size_t i = 0; i < msg_count; i++) {
StructuredData::ObjectSP message = messages_array->GetItemAtIndex(i);
- if (message &&
- message->GetType() == StructuredData::Type::eTypeDictionary) {
+ if (message && message->GetType() == eStructuredDataTypeDictionary) {
StructuredData::Dictionary *message_dict =
message->GetAsDictionary();
StructuredData::ObjectSP message_text =
message_dict->GetValueForKey("message");
if (message_text &&
- message_text->GetType() == StructuredData::Type::eTypeString) {
+ message_text->GetType() == eStructuredDataTypeString) {
strm.Format(" {0}\n", message_text->GetAsString()->GetValue());
}
}
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index a94f6bcd0087..cf5c7e227448 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -280,6 +280,15 @@ uint64_t StringExtractor::GetHexMaxU64(bool little_endian,
return result;
}
+bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
+ llvm::StringRef S = GetStringRef();
+ if (!S.startswith(str))
+ return false;
+ else
+ m_index += str.size();
+ return true;
+}
+
size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
uint8_t fail_fill_value) {
size_t bytes_extracted = 0;
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index 08226f4c8f90..3473a9e96689 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -286,6 +286,16 @@ StringExtractorGDBRemote::GetServerPacketType() const {
return eServerPacketType_jSignalsInfo;
if (PACKET_MATCHES("jThreadsInfo"))
return eServerPacketType_jThreadsInfo;
+ if (PACKET_STARTS_WITH("jTraceBufferRead:"))
+ return eServerPacketType_jTraceBufferRead;
+ if (PACKET_STARTS_WITH("jTraceConfigRead:"))
+ return eServerPacketType_jTraceConfigRead;
+ if (PACKET_STARTS_WITH("jTraceMetaRead:"))
+ return eServerPacketType_jTraceMetaRead;
+ if (PACKET_STARTS_WITH("jTraceStart:"))
+ return eServerPacketType_jTraceStart;
+ if (PACKET_STARTS_WITH("jTraceStop:"))
+ return eServerPacketType_jTraceStop;
break;
case 'v':
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
index a5c0c8e803b6..473cab04f800 100644
--- a/source/Utility/StringExtractorGDBRemote.h
+++ b/source/Utility/StringExtractorGDBRemote.h
@@ -164,6 +164,12 @@ public:
eServerPacketType__M,
eServerPacketType__m,
eServerPacketType_notify, // '%' notification
+
+ eServerPacketType_jTraceStart,
+ eServerPacketType_jTraceBufferRead,
+ eServerPacketType_jTraceMetaRead,
+ eServerPacketType_jTraceStop,
+ eServerPacketType_jTraceConfigRead,
};
ServerPacketType GetServerPacketType() const;
diff --git a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index 56a7e74269aa..c9ab0b6050a0 100644
--- a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -11,8 +11,10 @@
#include "GDBRemoteTestUtils.h"
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
+#include "lldb/lldb-enumerations.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/StructuredData.h"
+#include "lldb/Core/TraceOptions.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/DataBuffer.h"
@@ -370,3 +372,227 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfoInvalidResponse) {
HandlePacket(server, "qMemoryRegionInfo:4000", "start:4000;size:0000;");
EXPECT_FALSE(result.get().Success());
}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) {
+ TestClient client;
+ MockServer server;
+ Connect(client, server);
+ if (HasFailure())
+ return;
+
+ TraceOptions options;
+ Status error;
+
+ options.setType(lldb::TraceType::eTraceTypeProcessorTrace);
+ options.setMetaDataBufferSize(8192);
+ options.setTraceBufferSize(8192);
+ options.setThreadID(0x23);
+
+ StructuredData::DictionarySP custom_params =
+ std::make_shared<StructuredData::Dictionary>();
+ custom_params->AddStringItem("tracetech", "intel-pt");
+ custom_params->AddIntegerItem("psb", 0x01);
+
+ options.setTraceParams(custom_params);
+
+ std::future<lldb::user_id_t> result = std::async(std::launch::async, [&] {
+ return client.SendStartTracePacket(options, error);
+ });
+
+ // Since the line is exceeding 80 characters.
+ std::string expected_packet1 =
+ R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" :)";
+ std::string expected_packet2 =
+ R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})";
+ HandlePacket(server, (expected_packet1 + expected_packet2), "1");
+ ASSERT_TRUE(error.Success());
+ ASSERT_EQ(result.get(), 1);
+
+ error.Clear();
+ result = std::async(std::launch::async, [&] {
+ return client.SendStartTracePacket(options, error);
+ });
+
+ HandlePacket(server, (expected_packet1 + expected_packet2), "E23");
+ ASSERT_EQ(result.get(), LLDB_INVALID_UID);
+ ASSERT_FALSE(error.Success());
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendStopTracePacket) {
+ TestClient client;
+ MockServer server;
+ Connect(client, server);
+ if (HasFailure())
+ return;
+
+ lldb::tid_t thread_id = 0x23;
+ lldb::user_id_t trace_id = 3;
+
+ std::future<Status> result = std::async(std::launch::async, [&] {
+ return client.SendStopTracePacket(trace_id, thread_id);
+ });
+
+ const char *expected_packet =
+ R"(jTraceStop:{"threadid" : 35,"traceid" : 3})";
+ HandlePacket(server, expected_packet, "OK");
+ ASSERT_TRUE(result.get().Success());
+
+ result = std::async(std::launch::async, [&] {
+ return client.SendStopTracePacket(trace_id, thread_id);
+ });
+
+ HandlePacket(server, expected_packet, "E23");
+ ASSERT_FALSE(result.get().Success());
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) {
+ TestClient client;
+ MockServer server;
+ Connect(client, server);
+ if (HasFailure())
+ return;
+
+ lldb::tid_t thread_id = 0x23;
+ lldb::user_id_t trace_id = 3;
+
+ uint8_t buf[32] = {};
+ llvm::MutableArrayRef<uint8_t> buffer(buf, 32);
+ size_t offset = 0;
+
+ std::future<Status> result = std::async(std::launch::async, [&] {
+ return client.SendGetDataPacket(trace_id, thread_id, buffer, offset);
+ });
+
+ std::string expected_packet1 =
+ R"(jTraceBufferRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)";
+ std::string expected_packet2 = R"("traceid" : 3})";
+ HandlePacket(server, expected_packet1+expected_packet2, "123456");
+ ASSERT_TRUE(result.get().Success());
+ ASSERT_EQ(buffer.size(), 3);
+ ASSERT_EQ(buf[0], 0x12);
+ ASSERT_EQ(buf[1], 0x34);
+ ASSERT_EQ(buf[2], 0x56);
+
+ llvm::MutableArrayRef<uint8_t> buffer2(buf, 32);
+ result = std::async(std::launch::async, [&] {
+ return client.SendGetDataPacket(trace_id, thread_id, buffer2, offset);
+ });
+
+ HandlePacket(server, expected_packet1+expected_packet2, "E23");
+ ASSERT_FALSE(result.get().Success());
+ ASSERT_EQ(buffer2.size(), 0);
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) {
+ TestClient client;
+ MockServer server;
+ Connect(client, server);
+ if (HasFailure())
+ return;
+
+ lldb::tid_t thread_id = 0x23;
+ lldb::user_id_t trace_id = 3;
+
+ uint8_t buf[32] = {};
+ llvm::MutableArrayRef<uint8_t> buffer(buf, 32);
+ size_t offset = 0;
+
+ std::future<Status> result = std::async(std::launch::async, [&] {
+ return client.SendGetMetaDataPacket(trace_id, thread_id, buffer, offset);
+ });
+
+ std::string expected_packet1 =
+ R"(jTraceMetaRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)";
+ std::string expected_packet2 = R"("traceid" : 3})";
+ HandlePacket(server, expected_packet1+expected_packet2, "123456");
+ ASSERT_TRUE(result.get().Success());
+ ASSERT_EQ(buffer.size(), 3);
+ ASSERT_EQ(buf[0], 0x12);
+ ASSERT_EQ(buf[1], 0x34);
+ ASSERT_EQ(buf[2], 0x56);
+
+ llvm::MutableArrayRef<uint8_t> buffer2(buf, 32);
+ result = std::async(std::launch::async, [&] {
+ return client.SendGetMetaDataPacket(trace_id, thread_id, buffer2, offset);
+ });
+
+ HandlePacket(server, expected_packet1+expected_packet2, "E23");
+ ASSERT_FALSE(result.get().Success());
+ ASSERT_EQ(buffer2.size(), 0);
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) {
+ TestClient client;
+ MockServer server;
+ Connect(client, server);
+ if (HasFailure())
+ return;
+
+ lldb::tid_t thread_id = 0x23;
+ lldb::user_id_t trace_id = 3;
+ TraceOptions options;
+ options.setThreadID(thread_id);
+
+ std::future<Status> result = std::async(std::launch::async, [&] {
+ return client.SendGetTraceConfigPacket(trace_id, options);
+ });
+
+ const char *expected_packet =
+ R"(jTraceConfigRead:{"threadid" : 35,"traceid" : 3})";
+ std::string response1 =
+ R"({"buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})";
+ std::string response2 =
+ R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+ HandlePacket(server, expected_packet, response1+response2);
+ ASSERT_TRUE(result.get().Success());
+ ASSERT_EQ(options.getTraceBufferSize(), 8192);
+ ASSERT_EQ(options.getMetaDataBufferSize(), 8192);
+ ASSERT_EQ(options.getType(), 1);
+
+ auto custom_params = options.getTraceParams();
+
+ uint64_t psb_value;
+ llvm::StringRef trace_tech_value;
+
+ ASSERT_TRUE(custom_params);
+ ASSERT_EQ(custom_params->GetType(), eStructuredDataTypeDictionary);
+ ASSERT_TRUE(
+ custom_params->GetValueForKeyAsInteger<uint64_t>("psb", psb_value));
+ ASSERT_EQ(psb_value, 1);
+ ASSERT_TRUE(
+ custom_params->GetValueForKeyAsString("tracetech", trace_tech_value));
+ ASSERT_STREQ(trace_tech_value.data(), "intel-pt");
+
+ // Checking error response.
+ std::future<Status> result2 = std::async(std::launch::async, [&] {
+ return client.SendGetTraceConfigPacket(trace_id, options);
+ });
+
+ HandlePacket(server, expected_packet, "E23");
+ ASSERT_FALSE(result2.get().Success());
+
+ // Wrong JSON as response.
+ std::future<Status> result3 = std::async(std::launch::async, [&] {
+ return client.SendGetTraceConfigPacket(trace_id, options);
+ });
+
+ std::string incorrect_json1 =
+ R"("buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})";
+ std::string incorrect_json2 =
+ R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+ HandlePacket(server, expected_packet, incorrect_json1+incorrect_json2);
+ ASSERT_FALSE(result3.get().Success());
+
+ // Wrong JSON as custom_params.
+ std::future<Status> result4 = std::async(std::launch::async, [&] {
+ return client.SendGetTraceConfigPacket(trace_id, options);
+ });
+
+ std::string incorrect_custom_params1 =
+ R"({"buffersize" : 8192,"params" : "psb" : 1,"tracetech" : "intel-pt"})";
+ std::string incorrect_custom_params2 =
+ R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+ HandlePacket(server, expected_packet, incorrect_custom_params1+
+ incorrect_custom_params2);
+ ASSERT_FALSE(result4.get().Success());
+}
diff --git a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
index 192e64d07034..1376f268aa79 100644
--- a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
+++ b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
@@ -15,6 +15,7 @@
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/lldb-enumerations.h"
#include "PythonTestSuite.h"
@@ -355,9 +356,9 @@ TEST_F(PythonDataObjectsTest, TestPythonListToStructuredList) {
list.AppendItem(PythonString(string_value1));
auto array_sp = list.CreateStructuredArray();
- EXPECT_EQ(StructuredData::Type::eTypeInteger,
+ EXPECT_EQ(lldb::eStructuredDataTypeInteger,
array_sp->GetItemAtIndex(0)->GetType());
- EXPECT_EQ(StructuredData::Type::eTypeString,
+ EXPECT_EQ(lldb::eStructuredDataTypeString,
array_sp->GetItemAtIndex(1)->GetType());
auto int_sp = array_sp->GetItemAtIndex(0)->GetAsInteger();
@@ -424,9 +425,9 @@ TEST_F(PythonDataObjectsTest, TestPythonTupleToStructuredList) {
auto array_sp = tuple.CreateStructuredArray();
EXPECT_EQ(tuple.GetSize(), array_sp->GetSize());
- EXPECT_EQ(StructuredData::Type::eTypeInteger,
+ EXPECT_EQ(lldb::eStructuredDataTypeInteger,
array_sp->GetItemAtIndex(0)->GetType());
- EXPECT_EQ(StructuredData::Type::eTypeString,
+ EXPECT_EQ(lldb::eStructuredDataTypeString,
array_sp->GetItemAtIndex(1)->GetType());
}