Vendor import of lldb trunk r304149:

https://llvm.org/svn/llvm-project/lldb/trunk@304149
This commit is contained in:
Dimitry Andric 2017-05-29 16:26:31 +00:00
parent fb19dde5bf
commit 61b440f500
44 changed files with 1735 additions and 243 deletions

View File

@ -208,6 +208,163 @@ This packet must be sent _prior_ to sending a "A" packet.
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>"
//

View File

@ -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 */

View File

@ -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.
//------------------------------------------------------------------

View File

@ -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);
}
Dictionary *GetAsDictionary() {
return ((m_type == Type::eTypeDictionary)
? static_cast<Dictionary *>(this)
return ((m_type == lldb::eStructuredDataTypeArray)
? static_cast<Array *>(this)
: nullptr);
}
Dictionary *GetAsDictionary() {
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; }

View File

@ -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;
}
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

View File

@ -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;

View File

@ -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

View File

@ -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_

View File

@ -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:

View File

@ -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;

View File

@ -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),

View File

@ -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")

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
LEVEL = ../../make
LEVEL = ../../../make
CXX_SOURCES := main.cpp
ENABLE_THREADS := YES

View File

@ -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))

View File

@ -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;

View File

@ -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");

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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)));
}
}

View File

@ -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.");
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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",

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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);
};

View File

@ -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) {
@ -1083,6 +1099,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) {

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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 "

View File

@ -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());
}
}

View File

@ -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;

View File

@ -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':

View File

@ -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;

View File

@ -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());
}

View File

@ -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());
}