Add StructuredData plugin type; showcase with new DarwinLog feature

Take 2, with missing cmake line fixed.  Build tested on
Ubuntu 14.04 with clang-3.6.

See docs/structured_data/StructuredDataPlugins.md for details.

differential review: https://reviews.llvm.org/D22976

reviewers: clayborg, jingham
llvm-svn: 279202
This commit is contained in:
Todd Fiala
2016-08-19 04:21:48 +00:00
parent e2ca3b65fc
commit 759300192a
131 changed files with 11358 additions and 61 deletions

View File

@@ -54,6 +54,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/StructuredDataPlugin.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
@@ -797,6 +798,7 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, const UnixSig
SetEventName(eBroadcastBitSTDOUT, "stdout-available");
SetEventName(eBroadcastBitSTDERR, "stderr-available");
SetEventName(eBroadcastBitProfileData, "profile-data-available");
SetEventName(eBroadcastBitStructuredData, "structured-data-available");
m_private_state_control_broadcaster.SetEventName(eBroadcastInternalStateControlStop, "control-stop");
m_private_state_control_broadcaster.SetEventName(eBroadcastInternalStateControlPause, "control-pause");
@@ -804,7 +806,8 @@ Process::Process(lldb::TargetSP target_sp, ListenerSP listener_sp, const UnixSig
m_listener_sp->StartListeningForEvents(this, eBroadcastBitStateChanged | eBroadcastBitInterrupt |
eBroadcastBitSTDOUT | eBroadcastBitSTDERR |
eBroadcastBitProfileData);
eBroadcastBitProfileData |
eBroadcastBitStructuredData);
m_private_state_listener_sp->StartListeningForEvents(&m_private_state_broadcaster,
eBroadcastBitStateChanged | eBroadcastBitInterrupt);
@@ -4795,6 +4798,25 @@ Process::BroadcastAsyncProfileData(const std::string &one_profile_data)
BroadcastEventIfUnique (eBroadcastBitProfileData, new ProcessEventData (shared_from_this(), GetState()));
}
void
Process::BroadcastStructuredData(const StructuredData::ObjectSP &object_sp,
const StructuredDataPluginSP &plugin_sp)
{
BroadcastEvent(eBroadcastBitStructuredData,
new EventDataStructuredData(shared_from_this(),
object_sp, plugin_sp));
}
StructuredDataPluginSP
Process::GetStructuredDataPlugin(const ConstString &type_name) const
{
auto find_it = m_structured_data_plugin_map.find(type_name);
if (find_it != m_structured_data_plugin_map.end())
return find_it->second;
else
return StructuredDataPluginSP();
}
size_t
Process::GetAsyncProfileData (char *buf, size_t buf_size, Error &error)
{
@@ -6381,6 +6403,13 @@ Process::ModulesDidLoad (ModuleList &module_list)
// loading shared libraries might cause a new one to try and load
if (!m_os_ap)
LoadOperatingSystemPlugin(false);
// Give structured-data plugins a chance to see the modified modules.
for (auto pair : m_structured_data_plugin_map)
{
if (pair.second)
pair.second->ModulesDidLoad(*this, module_list);
}
}
void
@@ -6598,5 +6627,129 @@ Process::GetMemoryRegions (std::vector<lldb::MemoryRegionInfoSP>& region_list)
} while (range_end != LLDB_INVALID_ADDRESS);
return error;
}
Error
Process::ConfigureStructuredData(const ConstString &type_name,
const StructuredData::ObjectSP &config_sp)
{
// If you get this, the Process-derived class needs to implement a method
// to enable an already-reported asynchronous structured data feature.
// See ProcessGDBRemote for an example implementation over gdb-remote.
return Error("unimplemented");
}
void
Process::MapSupportedStructuredDataPlugins(const StructuredData::Array
&supported_type_names)
{
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
// Bail out early if there are no type names to map.
if (supported_type_names.GetSize() == 0)
{
if (log)
log->Printf("Process::%s(): no structured data types supported",
__FUNCTION__);
return;
}
// Convert StructuredData type names to ConstString instances.
std::set<ConstString> const_type_names;
if (log)
log->Printf("Process::%s(): the process supports the following async "
"structured data types:", __FUNCTION__);
supported_type_names.ForEach([&const_type_names, &log]
(StructuredData::Object *object) {
if (!object)
{
// Invalid - shouldn't be null objects in the array.
return false;
}
auto type_name = object->GetAsString();
if (!type_name)
{
// Invalid format - all type names should be strings.
return false;
}
const_type_names.insert(ConstString(type_name->GetValue()));
if (log)
log->Printf("- %s", type_name->GetValue().c_str());
return true;
});
// For each StructuredDataPlugin, if the plugin handles any of the
// types in the supported_type_names, map that type name to that plugin.
uint32_t plugin_index = 0;
for (auto create_instance =
PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(plugin_index);
create_instance && !const_type_names.empty();
++plugin_index)
{
// Create the plugin.
StructuredDataPluginSP plugin_sp = (*create_instance)(*this);
if (!plugin_sp)
{
// This plugin doesn't think it can work with the process.
// Move on to the next.
continue;
}
// For any of the remaining type names, map any that this plugin
// supports.
std::vector<ConstString> names_to_remove;
for (auto &type_name : const_type_names)
{
if (plugin_sp->SupportsStructuredDataType(type_name))
{
m_structured_data_plugin_map.insert(std::make_pair(type_name,
plugin_sp));
names_to_remove.push_back(type_name);
if (log)
log->Printf("Process::%s(): using plugin %s for type name "
"%s", __FUNCTION__,
plugin_sp->GetPluginName().GetCString(),
type_name.GetCString());
}
}
// Remove the type names that were consumed by this plugin.
for (auto &type_name : names_to_remove)
const_type_names.erase(type_name);
}
}
bool
Process::RouteAsyncStructuredData(const StructuredData::ObjectSP object_sp)
{
// Nothing to do if there's no data.
if (!object_sp)
return false;
// The contract is this must be a dictionary, so we can look up the
// routing key via the top-level 'type' string value within the dictionary.
StructuredData::Dictionary *dictionary = object_sp->GetAsDictionary();
if (!dictionary)
return false;
// Grab the async structured type name (i.e. the feature/plugin name).
ConstString type_name;
if (!dictionary->GetValueForKeyAsString("type", type_name))
return false;
// Check if there's a plugin registered for this type name.
auto find_it = m_structured_data_plugin_map.find(type_name);
if (find_it == m_structured_data_plugin_map.end())
{
// We don't have a mapping for this structured data type.
return false;
}
// Route the structured data to the plugin.
find_it->second->HandleArrivalOfStructuredData(*this, type_name, object_sp);
return true;
}