Initial implementation of SB APIs for Tracing support.
Summary:
This patch introduces new SB APIs for tracing support
inside LLDB. The idea is to gather trace data from
LLDB and provide it through this APIs to external
tools integrating with LLDB. These tools will be
responsible for interpreting and presenting the
trace data to their users.
The patch implements the following new SB APIs ->
-> StartTrace - starts tracing with given parameters
-> StopTrace - stops tracing.
-> GetTraceData - read the trace data .
-> GetMetaData - read the meta data assosciated with the trace.
-> GetTraceConfig - read the trace configuration
Tracing is associated with a user_id that is returned
by the StartTrace API and this id needs to be used
for accessing the trace data and also Stopping
the trace. The user_id itself may map to tracing
the complete process or just an individual thread.
The APIs require an additional thread parameter
when the user of these APIs wishes to perform
thread specific manipulations on the tracing instances.
The patch also includes the corresponding
python wrappers for the C++ based APIs.
Reviewers: k8stone, lldb-commits, clayborg
Reviewed By: clayborg
Subscribers: jingham, mgorny
Differential Revision: https://reviews.llvm.org/D29581
llvm-svn: 301389
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index 3b852a3..9dd21bc 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -67,6 +67,8 @@
SBThread.cpp
SBThreadCollection.cpp
SBThreadPlan.cpp
+ SBTrace.cpp
+ SBTraceOptions.cpp
SBType.cpp
SBTypeCategory.cpp
SBTypeEnumMember.cpp
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 4cb367a..5614cb4 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -44,6 +44,8 @@
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
+#include "lldb/API/SBTrace.h"
+#include "lldb/API/SBTraceOptions.h"
#include "lldb/API/SBUnixSignals.h"
using namespace lldb;
@@ -349,6 +351,26 @@
return bytes_read;
}
+lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options,
+ lldb::SBError &error) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ ProcessSP process_sp(GetSP());
+ error.Clear();
+ SBTrace trace_instance;
+ trace_instance.SetSP(process_sp);
+ lldb::user_id_t uid = LLDB_INVALID_UID;
+
+ if (!process_sp) {
+ error.SetErrorString("invalid process");
+ } else {
+
+ uid = process_sp->StartTrace(options.m_traceoptions_sp, error.ref());
+ trace_instance.SetTraceUID(uid);
+ LLDB_LOG(log, "SBProcess::returned uid - %" PRIx64, uid);
+ }
+ return trace_instance;
+}
+
void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const {
if (out == NULL)
return;
diff --git a/lldb/source/API/SBStructuredData.cpp b/lldb/source/API/SBStructuredData.cpp
index 6d4c862..2fca56f 100644
--- a/lldb/source/API/SBStructuredData.cpp
+++ b/lldb/source/API/SBStructuredData.cpp
@@ -12,6 +12,7 @@
#include "lldb/API/SBStream.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/StructuredData.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Target/StructuredDataPlugin.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/Stream.h"
@@ -20,70 +21,6 @@
using namespace lldb_private;
#pragma mark--
-#pragma mark StructuredDataImpl
-
-class StructuredDataImpl {
-public:
- StructuredDataImpl() : m_plugin_wp(), m_data_sp() {}
-
- StructuredDataImpl(const StructuredDataImpl &rhs) = default;
-
- StructuredDataImpl(const EventSP &event_sp)
- : m_plugin_wp(
- EventDataStructuredData::GetPluginFromEvent(event_sp.get())),
- m_data_sp(EventDataStructuredData::GetObjectFromEvent(event_sp.get())) {
- }
-
- ~StructuredDataImpl() = default;
-
- StructuredDataImpl &operator=(const StructuredDataImpl &rhs) = default;
-
- bool IsValid() const { return m_data_sp.get() != nullptr; }
-
- void Clear() {
- m_plugin_wp.reset();
- m_data_sp.reset();
- }
-
- SBError GetAsJSON(lldb_private::Stream &stream) const {
- SBError sb_error;
-
- if (!m_data_sp) {
- sb_error.SetErrorString("No structured data.");
- return sb_error;
- }
-
- m_data_sp->Dump(stream);
- return sb_error;
- }
-
- Error GetDescription(lldb_private::Stream &stream) const {
- Error error;
-
- if (!m_data_sp) {
- error.SetErrorString("Cannot pretty print structured data: "
- "no data to print.");
- return error;
- }
-
- // Grab the plugin.
- auto plugin_sp = StructuredDataPluginSP(m_plugin_wp);
- if (!plugin_sp) {
- error.SetErrorString("Cannot pretty print structured data: "
- "plugin doesn't exist.");
- return error;
- }
-
- // Get the data's description.
- return plugin_sp->GetDescription(m_data_sp, stream);
- }
-
-private:
- StructuredDataPluginWP m_plugin_wp;
- StructuredData::ObjectSP m_data_sp;
-};
-
-#pragma mark--
#pragma mark SBStructuredData
SBStructuredData::SBStructuredData() : m_impl_up(new StructuredDataImpl()) {}
@@ -102,12 +39,26 @@
return *this;
}
+lldb::SBError SBStructuredData::SetFromJSON(lldb::SBStream &stream) {
+ lldb::SBError error;
+ std::string json_str(stream.GetData());
+
+ StructuredData::ObjectSP json_obj = StructuredData::ParseJSON(json_str);
+ m_impl_up->SetObjectSP(json_obj);
+
+ if (!json_obj || json_obj->GetType() != StructuredData::Type::eTypeDictionary)
+ error.SetErrorString("Invalid Syntax");
+ return error;
+}
+
bool SBStructuredData::IsValid() const { return m_impl_up->IsValid(); }
void SBStructuredData::Clear() { m_impl_up->Clear(); }
SBError SBStructuredData::GetAsJSON(lldb::SBStream &stream) const {
- return m_impl_up->GetAsJSON(stream.ref());
+ SBError error;
+ error.SetError(m_impl_up->GetAsJSON(stream.ref()));
+ return error;
}
lldb::SBError SBStructuredData::GetDescription(lldb::SBStream &stream) const {
diff --git a/lldb/source/API/SBTrace.cpp b/lldb/source/API/SBTrace.cpp
new file mode 100644
index 0000000..18f7d36
--- /dev/null
+++ b/lldb/source/API/SBTrace.cpp
@@ -0,0 +1,109 @@
+//===-- SBTrace.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Target/Process.h"
+
+#include "lldb/API/SBTrace.h"
+#include "lldb/API/SBTraceOptions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class TraceImpl {
+public:
+ lldb::user_id_t uid;
+};
+
+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));
+ 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);
+ }
+ return bytes_read;
+}
+
+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));
+ 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);
+ }
+ return bytes_read;
+}
+
+void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) {
+ ProcessSP process_sp(GetSP());
+ error.Clear();
+
+ if (!process_sp) {
+ error.SetErrorString("invalid process");
+ return;
+ }
+ process_sp->StopTrace(GetTraceUID(), thread_id, error.ref());
+}
+
+void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
+ ProcessSP process_sp(GetSP());
+ error.Clear();
+
+ if (!process_sp) {
+ error.SetErrorString("invalid process");
+ } else {
+ process_sp->GetTraceConfig(GetTraceUID(), error.ref(),
+ options.m_traceoptions_sp);
+ }
+}
+
+lldb::user_id_t SBTrace::GetTraceUID() {
+ if (m_trace_impl_sp)
+ return m_trace_impl_sp->uid;
+ return LLDB_INVALID_UID;
+}
+
+void SBTrace::SetTraceUID(lldb::user_id_t uid) {
+ if (m_trace_impl_sp)
+ m_trace_impl_sp->uid = uid;
+}
+
+SBTrace::SBTrace() {
+ m_trace_impl_sp.reset(new TraceImpl);
+ if (m_trace_impl_sp)
+ m_trace_impl_sp->uid = LLDB_INVALID_UID;
+}
+
+void SBTrace::SetSP(const ProcessSP &process_sp) { m_opaque_wp = process_sp; }
+
+bool SBTrace::IsValid() {
+ if (!m_trace_impl_sp)
+ return false;
+ if (!GetSP())
+ return false;
+ return true;
+}
diff --git a/lldb/source/API/SBTraceOptions.cpp b/lldb/source/API/SBTraceOptions.cpp
new file mode 100644
index 0000000..474fa91
--- /dev/null
+++ b/lldb/source/API/SBTraceOptions.cpp
@@ -0,0 +1,94 @@
+//===-- SBTraceOptions.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBTraceOptions.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Core/StructuredDataImpl.h"
+#include "lldb/Core/TraceOptions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBTraceOptions::SBTraceOptions() {
+ m_traceoptions_sp.reset(new TraceOptions());
+}
+
+lldb::TraceType SBTraceOptions::getType() const {
+ if (m_traceoptions_sp)
+ return m_traceoptions_sp->getType();
+ return lldb::TraceType::eTraceTypeNone;
+}
+
+uint64_t SBTraceOptions::getTraceBufferSize() const {
+ if (m_traceoptions_sp)
+ return m_traceoptions_sp->getTraceBufferSize();
+ return 0;
+}
+
+lldb::SBStructuredData SBTraceOptions::getTraceParams(lldb::SBError &error) {
+ error.Clear();
+ const lldb_private::StructuredData::DictionarySP dict_obj =
+ m_traceoptions_sp->getTraceParams();
+ lldb::SBStructuredData structData;
+ if (dict_obj && structData.m_impl_up)
+ structData.m_impl_up->SetObjectSP(dict_obj->shared_from_this());
+ else
+ error.SetErrorString("Empty trace params");
+ return structData;
+}
+
+uint64_t SBTraceOptions::getMetaDataBufferSize() const {
+ if (m_traceoptions_sp)
+ return m_traceoptions_sp->getTraceBufferSize();
+ return 0;
+}
+
+void SBTraceOptions::setTraceParams(lldb::SBStructuredData ¶ms) {
+ if (m_traceoptions_sp && params.m_impl_up) {
+ StructuredData::ObjectSP obj_sp = params.m_impl_up->GetObjectSP();
+ if (obj_sp && obj_sp->GetAsDictionary() != nullptr)
+ m_traceoptions_sp->setTraceParams(
+ std::static_pointer_cast<StructuredData::Dictionary>(obj_sp));
+ }
+ return;
+}
+
+void SBTraceOptions::setType(lldb::TraceType type) {
+ if (m_traceoptions_sp)
+ m_traceoptions_sp->setType(type);
+}
+
+void SBTraceOptions::setTraceBufferSize(uint64_t size) {
+ if (m_traceoptions_sp)
+ m_traceoptions_sp->setTraceBufferSize(size);
+}
+
+void SBTraceOptions::setMetaDataBufferSize(uint64_t size) {
+ if (m_traceoptions_sp)
+ m_traceoptions_sp->setMetaDataBufferSize(size);
+}
+
+bool SBTraceOptions::IsValid() {
+ if (m_traceoptions_sp)
+ return true;
+ return false;
+}
+
+void SBTraceOptions::setThreadID(lldb::tid_t thread_id) {
+ if (m_traceoptions_sp)
+ m_traceoptions_sp->setThreadID(thread_id);
+}
+
+lldb::tid_t SBTraceOptions::getThreadID() {
+ if (m_traceoptions_sp)
+ return m_traceoptions_sp->getThreadID();
+ return LLDB_INVALID_THREAD_ID;
+}