//===-- StructuredDataDarwinLog.cpp -----------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "StructuredDataDarwinLog.h"

// C includes
#include <string.h>

// C++ includes
#include <sstream>

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanCallOnFunctionExit.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"

#define DARWIN_LOG_TYPE_VALUE "DarwinLog"

using namespace lldb;
using namespace lldb_private;

#pragma mark -
#pragma mark Anonymous Namespace

// -----------------------------------------------------------------------------
// Anonymous namespace
// -----------------------------------------------------------------------------

namespace sddarwinlog_private {
const uint64_t NANOS_PER_MICRO = 1000;
const uint64_t NANOS_PER_MILLI = NANOS_PER_MICRO * 1000;
const uint64_t NANOS_PER_SECOND = NANOS_PER_MILLI * 1000;
const uint64_t NANOS_PER_MINUTE = NANOS_PER_SECOND * 60;
const uint64_t NANOS_PER_HOUR = NANOS_PER_MINUTE * 60;

static bool DEFAULT_FILTER_FALLTHROUGH_ACCEPTS = true;

//------------------------------------------------------------------
/// Global, sticky enable switch.  If true, the user has explicitly
/// run the enable command.  When a process launches or is attached to,
/// we will enable DarwinLog if either the settings for auto-enable is
/// on, or if the user had explicitly run enable at some point prior
/// to the launch/attach.
//------------------------------------------------------------------
static bool s_is_explicitly_enabled;

class EnableOptions;
using EnableOptionsSP = std::shared_ptr<EnableOptions>;

using OptionsMap =
    std::map<DebuggerWP, EnableOptionsSP, std::owner_less<DebuggerWP>>;

static OptionsMap &GetGlobalOptionsMap() {
  static OptionsMap s_options_map;
  return s_options_map;
}

static std::mutex &GetGlobalOptionsMapLock() {
  static std::mutex s_options_map_lock;
  return s_options_map_lock;
}

EnableOptionsSP GetGlobalEnableOptions(const DebuggerSP &debugger_sp) {
  if (!debugger_sp)
    return EnableOptionsSP();

  std::lock_guard<std::mutex> locker(GetGlobalOptionsMapLock());
  OptionsMap &options_map = GetGlobalOptionsMap();
  DebuggerWP debugger_wp(debugger_sp);
  auto find_it = options_map.find(debugger_wp);
  if (find_it != options_map.end())
    return find_it->second;
  else
    return EnableOptionsSP();
}

void SetGlobalEnableOptions(const DebuggerSP &debugger_sp,
                            const EnableOptionsSP &options_sp) {
  std::lock_guard<std::mutex> locker(GetGlobalOptionsMapLock());
  OptionsMap &options_map = GetGlobalOptionsMap();
  DebuggerWP debugger_wp(debugger_sp);
  auto find_it = options_map.find(debugger_wp);
  if (find_it != options_map.end())
    find_it->second = options_sp;
  else
    options_map.insert(std::make_pair(debugger_wp, options_sp));
}

#pragma mark -
#pragma mark Settings Handling

//------------------------------------------------------------------
/// Code to handle the StructuredDataDarwinLog settings
//------------------------------------------------------------------

static PropertyDefinition g_properties[] = {
    {
        "enable-on-startup",       // name
        OptionValue::eTypeBoolean, // type
        true,                      // global
        false,                     // default uint value
        nullptr,                   // default cstring value
        nullptr,                   // enum values
        "Enable Darwin os_log collection when debugged process is launched "
        "or attached." // description
    },
    {
        "auto-enable-options",    // name
        OptionValue::eTypeString, // type
        true,                     // global
        0,                        // default uint value
        "",                       // default cstring value
        nullptr,                  // enum values
        "Specify the options to 'plugin structured-data darwin-log enable' "
        "that should be applied when automatically enabling logging on "
        "startup/attach." // description
    },
    // Last entry sentinel.
    {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};

enum { ePropertyEnableOnStartup = 0, ePropertyAutoEnableOptions = 1 };

class StructuredDataDarwinLogProperties : public Properties {
public:
  static ConstString &GetSettingName() {
    static ConstString g_setting_name("darwin-log");
    return g_setting_name;
  }

  StructuredDataDarwinLogProperties() : Properties() {
    m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
    m_collection_sp->Initialize(g_properties);
  }

  virtual ~StructuredDataDarwinLogProperties() {}

  bool GetEnableOnStartup() const {
    const uint32_t idx = ePropertyEnableOnStartup;
    return m_collection_sp->GetPropertyAtIndexAsBoolean(
        nullptr, idx, g_properties[idx].default_uint_value != 0);
  }

  llvm::StringRef GetAutoEnableOptions() const {
    const uint32_t idx = ePropertyAutoEnableOptions;
    return m_collection_sp->GetPropertyAtIndexAsString(
        nullptr, idx, g_properties[idx].default_cstr_value);
  }

  const char *GetLoggingModuleName() const { return "libsystem_trace.dylib"; }
};

using StructuredDataDarwinLogPropertiesSP =
    std::shared_ptr<StructuredDataDarwinLogProperties>;

static const StructuredDataDarwinLogPropertiesSP &GetGlobalProperties() {
  static StructuredDataDarwinLogPropertiesSP g_settings_sp;
  if (!g_settings_sp)
    g_settings_sp.reset(new StructuredDataDarwinLogProperties());
  return g_settings_sp;
}

const char *const s_filter_attributes[] = {
    "activity",       // current activity
    "activity-chain", // entire activity chain, each level separated by ':'
    "category",       // category of the log message
    "message",        // message contents, fully expanded
    "subsystem"       // subsystem of the log message

    // Consider impelmenting this action as it would be cheaper to filter.
    // "message" requires always formatting the message, which is a waste
    // of cycles if it ends up being rejected.
    // "format",      // format string used to format message text
};

static const ConstString &GetDarwinLogTypeName() {
  static const ConstString s_key_name("DarwinLog");
  return s_key_name;
}

static const ConstString &GetLogEventType() {
  static const ConstString s_event_type("log");
  return s_event_type;
}

class FilterRule;
using FilterRuleSP = std::shared_ptr<FilterRule>;

class FilterRule {
public:
  virtual ~FilterRule() {}

  using OperationCreationFunc =
      std::function<FilterRuleSP(bool accept, size_t attribute_index,
                                 const std::string &op_arg, Status &error)>;

  static void RegisterOperation(const ConstString &operation,
                                const OperationCreationFunc &creation_func) {
    GetCreationFuncMap().insert(std::make_pair(operation, creation_func));
  }

  static FilterRuleSP CreateRule(bool match_accepts, size_t attribute,
                                 const ConstString &operation,
                                 const std::string &op_arg, Status &error) {
    // Find the creation func for this type of filter rule.
    auto map = GetCreationFuncMap();
    auto find_it = map.find(operation);
    if (find_it == map.end()) {
      error.SetErrorStringWithFormat("unknown filter operation \""
                                     "%s\"",
                                     operation.GetCString());
      return FilterRuleSP();
    }

    return find_it->second(match_accepts, attribute, op_arg, error);
  }

  StructuredData::ObjectSP Serialize() const {
    StructuredData::Dictionary *dict_p = new StructuredData::Dictionary();

    // Indicate whether this is an accept or reject rule.
    dict_p->AddBooleanItem("accept", m_accept);

    // Indicate which attribute of the message this filter references.
    // This can drop into the rule-specific DoSerialization if we get
    // to the point where not all FilterRule derived classes work on
    // an attribute.  (e.g. logical and/or and other compound
    // operations).
    dict_p->AddStringItem("attribute", s_filter_attributes[m_attribute_index]);

    // Indicate the type of the rule.
    dict_p->AddStringItem("type", GetOperationType().GetCString());

    // Let the rule add its own specific details here.
    DoSerialization(*dict_p);

    return StructuredData::ObjectSP(dict_p);
  }

  virtual void Dump(Stream &stream) const = 0;

  const ConstString &GetOperationType() const { return m_operation; }

protected:
  FilterRule(bool accept, size_t attribute_index, const ConstString &operation)
      : m_accept(accept), m_attribute_index(attribute_index),
        m_operation(operation) {}

  virtual void DoSerialization(StructuredData::Dictionary &dict) const = 0;

  bool GetMatchAccepts() const { return m_accept; }

  const char *GetFilterAttribute() const {
    return s_filter_attributes[m_attribute_index];
  }

private:
  using CreationFuncMap = std::map<ConstString, OperationCreationFunc>;

  static CreationFuncMap &GetCreationFuncMap() {
    static CreationFuncMap s_map;
    return s_map;
  }

  const bool m_accept;
  const size_t m_attribute_index;
  const ConstString m_operation;
};

using FilterRules = std::vector<FilterRuleSP>;

class RegexFilterRule : public FilterRule {
public:
  static void RegisterOperation() {
    FilterRule::RegisterOperation(StaticGetOperation(), CreateOperation);
  }

  void Dump(Stream &stream) const override {
    stream.Printf("%s %s regex %s", GetMatchAccepts() ? "accept" : "reject",
                  GetFilterAttribute(), m_regex_text.c_str());
  }

protected:
  void DoSerialization(StructuredData::Dictionary &dict) const override {
    dict.AddStringItem("regex", m_regex_text);
  }

private:
  static FilterRuleSP CreateOperation(bool accept, size_t attribute_index,
                                      const std::string &op_arg,
                                      Status &error) {
    // We treat the op_arg as a regex.  Validate it.
    if (op_arg.empty()) {
      error.SetErrorString("regex filter type requires a regex "
                           "argument");
      return FilterRuleSP();
    }

    // Instantiate the regex so we can report any errors.
    auto regex = RegularExpression(op_arg);
    if (!regex.IsValid()) {
      char error_text[256];
      error_text[0] = '\0';
      regex.GetErrorAsCString(error_text, sizeof(error_text));
      error.SetErrorString(error_text);
      return FilterRuleSP();
    }

    // We passed all our checks, this appears fine.
    error.Clear();
    return FilterRuleSP(new RegexFilterRule(accept, attribute_index, op_arg));
  }

  static const ConstString &StaticGetOperation() {
    static ConstString s_operation("regex");
    return s_operation;
  }

  RegexFilterRule(bool accept, size_t attribute_index,
                  const std::string &regex_text)
      : FilterRule(accept, attribute_index, StaticGetOperation()),
        m_regex_text(regex_text) {}

  const std::string m_regex_text;
};

class ExactMatchFilterRule : public FilterRule {
public:
  static void RegisterOperation() {
    FilterRule::RegisterOperation(StaticGetOperation(), CreateOperation);
  }

  void Dump(Stream &stream) const override {
    stream.Printf("%s %s match %s", GetMatchAccepts() ? "accept" : "reject",
                  GetFilterAttribute(), m_match_text.c_str());
  }

protected:
  void DoSerialization(StructuredData::Dictionary &dict) const override {
    dict.AddStringItem("exact_text", m_match_text);
  }

private:
  static FilterRuleSP CreateOperation(bool accept, size_t attribute_index,
                                      const std::string &op_arg,
                                      Status &error) {
    if (op_arg.empty()) {
      error.SetErrorString("exact match filter type requires an "
                           "argument containing the text that must "
                           "match the specified message attribute.");
      return FilterRuleSP();
    }

    error.Clear();
    return FilterRuleSP(
        new ExactMatchFilterRule(accept, attribute_index, op_arg));
  }

  static const ConstString &StaticGetOperation() {
    static ConstString s_operation("match");
    return s_operation;
  }

  ExactMatchFilterRule(bool accept, size_t attribute_index,
                       const std::string &match_text)
      : FilterRule(accept, attribute_index, StaticGetOperation()),
        m_match_text(match_text) {}

  const std::string m_match_text;
};

static void RegisterFilterOperations() {
  ExactMatchFilterRule::RegisterOperation();
  RegexFilterRule::RegisterOperation();
}

// =========================================================================
// Commands
// =========================================================================

// -------------------------------------------------------------------------
/// Provides the main on-off switch for enabling darwin logging.
///
/// It is valid to run the enable command when logging is already enabled.
/// This resets the logging with whatever settings are currently set.
// -------------------------------------------------------------------------

static OptionDefinition g_enable_option_table[] = {
    // Source stream include/exclude options (the first-level filter).
    // This one should be made as small as possible as everything that
    // goes through here must be processed by the process monitor.
    {LLDB_OPT_SET_ALL, false, "any-process", 'a', OptionParser::eNoArgument,
     nullptr, nullptr, 0, eArgTypeNone,
     "Specifies log messages from other related processes should be "
     "included."},
    {LLDB_OPT_SET_ALL, false, "debug", 'd', OptionParser::eNoArgument, nullptr,
     nullptr, 0, eArgTypeNone,
     "Specifies debug-level log messages should be included.  Specifying"
     " --debug implies --info."},
    {LLDB_OPT_SET_ALL, false, "info", 'i', OptionParser::eNoArgument, nullptr,
     nullptr, 0, eArgTypeNone,
     "Specifies info-level log messages should be included."},
    {LLDB_OPT_SET_ALL, false, "filter", 'f', OptionParser::eRequiredArgument,
     nullptr, nullptr, 0, eArgRawInput,
     // There doesn't appear to be a great way for me to have these
     // multi-line, formatted tables in help.  This looks mostly right
     // but there are extra linefeeds added at seemingly random spots,
     // and indentation isn't handled properly on those lines.
     "Appends a filter rule to the log message filter chain.  Multiple "
     "rules may be added by specifying this option multiple times, "
     "once per filter rule.  Filter rules are processed in the order "
     "they are specified, with the --no-match-accepts setting used "
     "for any message that doesn't match one of the rules.\n"
     "\n"
     "    Filter spec format:\n"
     "\n"
     "    --filter \"{action} {attribute} {op}\"\n"
     "\n"
     "    {action} :=\n"
     "      accept |\n"
     "      reject\n"
     "\n"
     "    {attribute} :=\n"
     "       activity       |  // message's most-derived activity\n"
     "       activity-chain |  // message's {parent}:{child} activity\n"
     "       category       |  // message's category\n"
     "       message        |  // message's expanded contents\n"
     "       subsystem      |  // message's subsystem\n"
     "\n"
     "    {op} :=\n"
     "      match {exact-match-text} |\n"
     "      regex {search-regex}\n"
     "\n"
     "The regex flavor used is the C++ std::regex ECMAScript format.  "
     "Prefer character classes like [[:digit:]] to \\d and the like, as "
     "getting the backslashes escaped through properly is error-prone."},
    {LLDB_OPT_SET_ALL, false, "live-stream", 'l',
     OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
     "Specify whether logging events are live-streamed or buffered.  "
     "True indicates live streaming, false indicates buffered.  The "
     "default is true (live streaming).  Live streaming will deliver "
     "log messages with less delay, but buffered capture mode has less "
     "of an observer effect."},
    {LLDB_OPT_SET_ALL, false, "no-match-accepts", 'n',
     OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
     "Specify whether a log message that doesn't match any filter rule "
     "is accepted or rejected, where true indicates accept.  The "
     "default is true."},
    {LLDB_OPT_SET_ALL, false, "echo-to-stderr", 'e',
     OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
     "Specify whether os_log()/NSLog() messages are echoed to the "
     "target program's stderr.  When DarwinLog is enabled, we shut off "
     "the mirroring of os_log()/NSLog() to the program's stderr.  "
     "Setting this flag to true will restore the stderr mirroring."
     "The default is false."},
    {LLDB_OPT_SET_ALL, false, "broadcast-events", 'b',
     OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
     "Specify if the plugin should broadcast events.  Broadcasting "
     "log events is a requirement for displaying the log entries in "
     "LLDB command-line.  It is also required if LLDB clients want to "
     "process log events.  The default is true."},
    // Message formatting options
    {LLDB_OPT_SET_ALL, false, "timestamp-relative", 'r',
     OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
     "Include timestamp in the message header when printing a log "
     "message.  The timestamp is relative to the first displayed "
     "message."},
    {LLDB_OPT_SET_ALL, false, "subsystem", 's', OptionParser::eNoArgument,
     nullptr, nullptr, 0, eArgTypeNone,
     "Include the subsystem in the the message header when displaying "
     "a log message."},
    {LLDB_OPT_SET_ALL, false, "category", 'c', OptionParser::eNoArgument,
     nullptr, nullptr, 0, eArgTypeNone,
     "Include the category in the the message header when displaying "
     "a log message."},
    {LLDB_OPT_SET_ALL, false, "activity-chain", 'C', OptionParser::eNoArgument,
     nullptr, nullptr, 0, eArgTypeNone,
     "Include the activity parent-child chain in the the message header "
     "when displaying a log message.  The activity hierarchy is "
     "displayed as {grandparent-activity}:"
     "{parent-activity}:{activity}[:...]."},
    {LLDB_OPT_SET_ALL, false, "all-fields", 'A', OptionParser::eNoArgument,
     nullptr, nullptr, 0, eArgTypeNone,
     "Shortcut to specify that all header fields should be displayed."}};

class EnableOptions : public Options {
public:
  EnableOptions()
      : Options(), m_include_debug_level(false), m_include_info_level(false),
        m_include_any_process(false),
        m_filter_fall_through_accepts(DEFAULT_FILTER_FALLTHROUGH_ACCEPTS),
        m_echo_to_stderr(false), m_display_timestamp_relative(false),
        m_display_subsystem(false), m_display_category(false),
        m_display_activity_chain(false), m_broadcast_events(true),
        m_live_stream(true), m_filter_rules() {}

  void OptionParsingStarting(ExecutionContext *execution_context) override {
    m_include_debug_level = false;
    m_include_info_level = false;
    m_include_any_process = false;
    m_filter_fall_through_accepts = DEFAULT_FILTER_FALLTHROUGH_ACCEPTS;
    m_echo_to_stderr = false;
    m_display_timestamp_relative = false;
    m_display_subsystem = false;
    m_display_category = false;
    m_display_activity_chain = false;
    m_broadcast_events = true;
    m_live_stream = true;
    m_filter_rules.clear();
  }

  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                        ExecutionContext *execution_context) override {
    Status error;

    const int short_option = m_getopt_table[option_idx].val;
    switch (short_option) {
    case 'a':
      m_include_any_process = true;
      break;

    case 'A':
      m_display_timestamp_relative = true;
      m_display_category = true;
      m_display_subsystem = true;
      m_display_activity_chain = true;
      break;

    case 'b':
      m_broadcast_events = Args::StringToBoolean(option_arg, true, nullptr);
      break;

    case 'c':
      m_display_category = true;
      break;

    case 'C':
      m_display_activity_chain = true;
      break;

    case 'd':
      m_include_debug_level = true;
      break;

    case 'e':
      m_echo_to_stderr = Args::StringToBoolean(option_arg, false, nullptr);
      break;

    case 'f':
      return ParseFilterRule(option_arg);

    case 'i':
      m_include_info_level = true;
      break;

    case 'l':
      m_live_stream = Args::StringToBoolean(option_arg, false, nullptr);
      break;

    case 'n':
      m_filter_fall_through_accepts =
          Args::StringToBoolean(option_arg, true, nullptr);
      break;

    case 'r':
      m_display_timestamp_relative = true;
      break;

    case 's':
      m_display_subsystem = true;
      break;

    default:
      error.SetErrorStringWithFormat("unsupported option '%c'", short_option);
    }
    return error;
  }

  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
    return llvm::makeArrayRef(g_enable_option_table);
  }

  StructuredData::DictionarySP BuildConfigurationData(bool enabled) {
    StructuredData::DictionarySP config_sp(new StructuredData::Dictionary());

    // Set the basic enabled state.
    config_sp->AddBooleanItem("enabled", enabled);

    // If we're disabled, there's nothing more to add.
    if (!enabled)
      return config_sp;

    // Handle source stream flags.
    auto source_flags_sp =
        StructuredData::DictionarySP(new StructuredData::Dictionary());
    config_sp->AddItem("source-flags", source_flags_sp);

    source_flags_sp->AddBooleanItem("any-process", m_include_any_process);
    source_flags_sp->AddBooleanItem("debug-level", m_include_debug_level);
    // The debug-level flag, if set, implies info-level.
    source_flags_sp->AddBooleanItem("info-level", m_include_info_level ||
                                                      m_include_debug_level);
    source_flags_sp->AddBooleanItem("live-stream", m_live_stream);

    // Specify default filter rule (the fall-through)
    config_sp->AddBooleanItem("filter-fall-through-accepts",
                              m_filter_fall_through_accepts);

    // Handle filter rules
    if (!m_filter_rules.empty()) {
      auto json_filter_rules_sp =
          StructuredData::ArraySP(new StructuredData::Array);
      config_sp->AddItem("filter-rules", json_filter_rules_sp);
      for (auto &rule_sp : m_filter_rules) {
        if (!rule_sp)
          continue;
        json_filter_rules_sp->AddItem(rule_sp->Serialize());
      }
    }
    return config_sp;
  }

  bool GetIncludeDebugLevel() const { return m_include_debug_level; }

  bool GetIncludeInfoLevel() const {
    // Specifying debug level implies info level.
    return m_include_info_level || m_include_debug_level;
  }

  const FilterRules &GetFilterRules() const { return m_filter_rules; }

  bool GetFallthroughAccepts() const { return m_filter_fall_through_accepts; }

  bool GetEchoToStdErr() const { return m_echo_to_stderr; }

  bool GetDisplayTimestampRelative() const {
    return m_display_timestamp_relative;
  }

  bool GetDisplaySubsystem() const { return m_display_subsystem; }
  bool GetDisplayCategory() const { return m_display_category; }
  bool GetDisplayActivityChain() const { return m_display_activity_chain; }

  bool GetDisplayAnyHeaderFields() const {
    return m_display_timestamp_relative || m_display_activity_chain ||
           m_display_subsystem || m_display_category;
  }

  bool GetBroadcastEvents() const { return m_broadcast_events; }

private:
  Status ParseFilterRule(llvm::StringRef rule_text) {
    Status error;

    if (rule_text.empty()) {
      error.SetErrorString("invalid rule_text");
      return error;
    }

    // filter spec format:
    //
    // {action} {attribute} {op}
    //
    // {action} :=
    //   accept |
    //   reject
    //
    // {attribute} :=
    //   category       |
    //   subsystem      |
    //   activity       |
    //   activity-chain |
    //   message        |
    //   format
    //
    // {op} :=
    //   match {exact-match-text} |
    //   regex {search-regex}

    // Parse action.
    auto action_end_pos = rule_text.find(" ");
    if (action_end_pos == std::string::npos) {
      error.SetErrorStringWithFormat("could not parse filter rule "
                                     "action from \"%s\"",
                                     rule_text.str().c_str());
      return error;
    }
    auto action = rule_text.substr(0, action_end_pos);
    bool accept;
    if (action == "accept")
      accept = true;
    else if (action == "reject")
      accept = false;
    else {
      error.SetErrorString("filter action must be \"accept\" or \"deny\"");
      return error;
    }

    // parse attribute
    auto attribute_end_pos = rule_text.find(" ", action_end_pos + 1);
    if (attribute_end_pos == std::string::npos) {
      error.SetErrorStringWithFormat("could not parse filter rule "
                                     "attribute from \"%s\"",
                                     rule_text.str().c_str());
      return error;
    }
    auto attribute = rule_text.substr(action_end_pos + 1,
                                      attribute_end_pos - (action_end_pos + 1));
    auto attribute_index = MatchAttributeIndex(attribute);
    if (attribute_index < 0) {
      error.SetErrorStringWithFormat("filter rule attribute unknown: "
                                     "%s",
                                     attribute.str().c_str());
      return error;
    }

    // parse operation
    auto operation_end_pos = rule_text.find(" ", attribute_end_pos + 1);
    auto operation = rule_text.substr(
        attribute_end_pos + 1, operation_end_pos - (attribute_end_pos + 1));

    // add filter spec
    auto rule_sp =
        FilterRule::CreateRule(accept, attribute_index, ConstString(operation),
                               rule_text.substr(operation_end_pos + 1), error);

    if (rule_sp && error.Success())
      m_filter_rules.push_back(rule_sp);

    return error;
  }

  int MatchAttributeIndex(llvm::StringRef attribute_name) const {
    for (const auto &Item : llvm::enumerate(s_filter_attributes)) {
      if (attribute_name == Item.value())
        return Item.index();
    }

    // We didn't match anything.
    return -1;
  }

  bool m_include_debug_level;
  bool m_include_info_level;
  bool m_include_any_process;
  bool m_filter_fall_through_accepts;
  bool m_echo_to_stderr;
  bool m_display_timestamp_relative;
  bool m_display_subsystem;
  bool m_display_category;
  bool m_display_activity_chain;
  bool m_broadcast_events;
  bool m_live_stream;
  FilterRules m_filter_rules;
};

class EnableCommand : public CommandObjectParsed {
public:
  EnableCommand(CommandInterpreter &interpreter, bool enable, const char *name,
                const char *help, const char *syntax)
      : CommandObjectParsed(interpreter, name, help, syntax), m_enable(enable),
        m_options_sp(enable ? new EnableOptions() : nullptr) {}

protected:
  void AppendStrictSourcesWarning(CommandReturnObject &result,
                                  const char *source_name) {
    if (!source_name)
      return;

    // Check if we're *not* using strict sources.  If not,
    // then the user is going to get debug-level info
    // anyways, probably not what they're expecting.
    // Unfortunately we can only fix this by adding an
    // env var, which would have had to have happened
    // already.  Thus, a warning is the best we can do here.
    StreamString stream;
    stream.Printf("darwin-log source settings specify to exclude "
                  "%s messages, but setting "
                  "'plugin.structured-data.darwin-log."
                  "strict-sources' is disabled.  This process will "
                  "automatically have %s messages included.  Enable"
                  " the property and relaunch the target binary to have"
                  " these messages excluded.",
                  source_name, source_name);
    result.AppendWarning(stream.GetString());
  }

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    // First off, set the global sticky state of enable/disable
    // based on this command execution.
    s_is_explicitly_enabled = m_enable;

    // Next, if this is an enable, save off the option data.
    // We will need it later if a process hasn't been launched or
    // attached yet.
    if (m_enable) {
      // Save off enabled configuration so we can apply these parsed
      // options the next time an attach or launch occurs.
      DebuggerSP debugger_sp =
          GetCommandInterpreter().GetDebugger().shared_from_this();
      SetGlobalEnableOptions(debugger_sp, m_options_sp);
    }

    // Now check if we have a running process.  If so, we should
    // instruct the process monitor to enable/disable DarwinLog support
    // now.
    Target *target = GetSelectedOrDummyTarget();
    if (!target) {
      // No target, so there is nothing more to do right now.
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return true;
    }

    // Grab the active process.
    auto process_sp = target->GetProcessSP();
    if (!process_sp) {
      // No active process, so there is nothing more to do right
      // now.
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return true;
    }

    // If the process is no longer alive, we can't do this now.
    // We'll catch it the next time the process is started up.
    if (!process_sp->IsAlive()) {
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      return true;
    }

    // Get the plugin for the process.
    auto plugin_sp =
        process_sp->GetStructuredDataPlugin(GetDarwinLogTypeName());
    if (!plugin_sp || (plugin_sp->GetPluginName() !=
                       StructuredDataDarwinLog::GetStaticPluginName())) {
      result.AppendError("failed to get StructuredDataPlugin for "
                         "the process");
      result.SetStatus(eReturnStatusFailed);
    }
    StructuredDataDarwinLog &plugin =
        *static_cast<StructuredDataDarwinLog *>(plugin_sp.get());

    if (m_enable) {
// To do this next part right, we need to track whether we
// added the proper environment variable at launch time.
// It is incorrect to assume that we're enabling after launch,
// and that therefore if we needed the env var set to properly
// handle the options, that it is set incorrectly.  The env var
// could have been added if this is a re-enable using different
// arguments.  This is a bit tricky as the point where we
// have to set the env var, we don't yet have a process or the
// associated darwin-log plugin instance, and thus don't have a
// great place to stick this knowledge.
#if 0
                // Check if we're attempting to disable debug-level or
                // info-level content but we haven't launched with the magic
                // env var that suppresses the "always add" of those.  In
                // that scenario, the user is asking *not* to see debug or
                // info level messages, but will see them anyway.  Warn and
                // show how to correct it.
                if (!m_options_sp->GetIncludeDebugLevel() &&
                    !GetGlobalProperties()->GetUseStrictSources())
                {
                    AppendStrictSourcesWarning(result, "debug-level");
                }

                if (!m_options_sp->GetIncludeInfoLevel() &&
                    !GetGlobalProperties()->GetUseStrictSources())
                {
                    AppendStrictSourcesWarning(result, "info-level");
                }
#endif

      // Hook up the breakpoint for the process that detects when
      // libtrace has been sufficiently initialized to really start
      // the os_log stream.  This is insurance to assure us that
      // logging is really enabled.  Requesting that logging be
      // enabled for a process before libtrace is initialized
      // results in a scenario where no errors occur, but no logging
      // is captured, either.  This step is to eliminate that
      // possibility.
      plugin.AddInitCompletionHook(*process_sp.get());
    }

    // Send configuration to the feature by way of the process.
    // Construct the options we will use.
    auto config_sp = m_options_sp->BuildConfigurationData(m_enable);
    const Status error =
        process_sp->ConfigureStructuredData(GetDarwinLogTypeName(), config_sp);

    // Report results.
    if (!error.Success()) {
      result.AppendError(error.AsCString());
      result.SetStatus(eReturnStatusFailed);
      // Our configuration failed, so we're definitely disabled.
      plugin.SetEnabled(false);
    } else {
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      // Our configuration succeeeded, so we're enabled/disabled
      // per whichever one this command is setup to do.
      plugin.SetEnabled(m_enable);
    }
    return result.Succeeded();
  }

  Options *GetOptions() override {
    // We don't have options when this represents disable.
    return m_enable ? m_options_sp.get() : nullptr;
  }

private:
  const bool m_enable;
  EnableOptionsSP m_options_sp;
};

// -------------------------------------------------------------------------
/// Provides the status command.
// -------------------------------------------------------------------------
class StatusCommand : public CommandObjectParsed {
public:
  StatusCommand(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "status",
                            "Show whether Darwin log supported is available"
                            " and enabled.",
                            "plugin structured-data darwin-log status") {}

protected:
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    auto &stream = result.GetOutputStream();

    // Figure out if we've got a process.  If so, we can tell if
    // DarwinLog is available for that process.
    Target *target = GetSelectedOrDummyTarget();
    auto process_sp = target ? target->GetProcessSP() : ProcessSP();
    if (!target || !process_sp) {
      stream.PutCString("Availability: unknown (requires process)\n");
      stream.PutCString("Enabled: not applicable "
                        "(requires process)\n");
    } else {
      auto plugin_sp =
          process_sp->GetStructuredDataPlugin(GetDarwinLogTypeName());
      stream.Printf("Availability: %s\n",
                    plugin_sp ? "available" : "unavailable");
      auto &plugin_name = StructuredDataDarwinLog::GetStaticPluginName();
      const bool enabled =
          plugin_sp ? plugin_sp->GetEnabled(plugin_name) : false;
      stream.Printf("Enabled: %s\n", enabled ? "true" : "false");
    }

    // Display filter settings.
    DebuggerSP debugger_sp =
        GetCommandInterpreter().GetDebugger().shared_from_this();
    auto options_sp = GetGlobalEnableOptions(debugger_sp);
    if (!options_sp) {
      // Nothing more to do.
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    }

    // Print filter rules
    stream.PutCString("DarwinLog filter rules:\n");

    stream.IndentMore();

    if (options_sp->GetFilterRules().empty()) {
      stream.Indent();
      stream.PutCString("none\n");
    } else {
      // Print each of the filter rules.
      int rule_number = 0;
      for (auto rule_sp : options_sp->GetFilterRules()) {
        ++rule_number;
        if (!rule_sp)
          continue;

        stream.Indent();
        stream.Printf("%02d: ", rule_number);
        rule_sp->Dump(stream);
        stream.PutChar('\n');
      }
    }
    stream.IndentLess();

    // Print no-match handling.
    stream.Indent();
    stream.Printf("no-match behavior: %s\n",
                  options_sp->GetFallthroughAccepts() ? "accept" : "reject");

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

// -------------------------------------------------------------------------
/// Provides the darwin-log base command
// -------------------------------------------------------------------------
class BaseCommand : public CommandObjectMultiword {
public:
  BaseCommand(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "plugin structured-data darwin-log",
                               "Commands for configuring Darwin os_log "
                               "support.",
                               "") {
    // enable
    auto enable_help = "Enable Darwin log collection, or re-enable "
                       "with modified configuration.";
    auto enable_syntax = "plugin structured-data darwin-log enable";
    auto enable_cmd_sp = CommandObjectSP(
        new EnableCommand(interpreter,
                          true, // enable
                          "enable", enable_help, enable_syntax));
    LoadSubCommand("enable", enable_cmd_sp);

    // disable
    auto disable_help = "Disable Darwin log collection.";
    auto disable_syntax = "plugin structured-data darwin-log disable";
    auto disable_cmd_sp = CommandObjectSP(
        new EnableCommand(interpreter,
                          false, // disable
                          "disable", disable_help, disable_syntax));
    LoadSubCommand("disable", disable_cmd_sp);

    // status
    auto status_cmd_sp = CommandObjectSP(new StatusCommand(interpreter));
    LoadSubCommand("status", status_cmd_sp);
  }
};

EnableOptionsSP ParseAutoEnableOptions(Status &error, Debugger &debugger) {
  // We are abusing the options data model here so that we can parse
  // options without requiring the Debugger instance.

  // We have an empty execution context at this point.  We only want
  // to parse options, and we don't need any context to do this here.
  // In fact, we want to be able to parse the enable options before having
  // any context.
  ExecutionContext exe_ctx;

  EnableOptionsSP options_sp(new EnableOptions());
  options_sp->NotifyOptionParsingStarting(&exe_ctx);

  CommandReturnObject result;

  // Parse the arguments.
  auto options_property_sp =
      debugger.GetPropertyValue(nullptr, "plugin.structured-data.darwin-log."
                                         "auto-enable-options",
                                false, error);
  if (!error.Success())
    return EnableOptionsSP();
  if (!options_property_sp) {
    error.SetErrorString("failed to find option setting for "
                         "plugin.structured-data.darwin-log.");
    return EnableOptionsSP();
  }

  const char *enable_options =
      options_property_sp->GetAsString()->GetCurrentValue();
  Args args(enable_options);
  if (args.GetArgumentCount() > 0) {
    // Eliminate the initial '--' that would be required to set the
    // settings that themselves include '-' and/or '--'.
    const char *first_arg = args.GetArgumentAtIndex(0);
    if (first_arg && (strcmp(first_arg, "--") == 0))
      args.Shift();
  }

  // ParseOptions calls getopt_long_only, which always skips the zero'th item in
  // the array and starts at position 1,
  // so we need to push a dummy value into position zero.
  args.Unshift(llvm::StringRef("dummy_string"));
  bool require_validation = false;
  error = args.ParseOptions(*options_sp.get(), &exe_ctx, PlatformSP(),
                            require_validation);
  if (!error.Success())
    return EnableOptionsSP();

  if (!options_sp->VerifyOptions(result))
    return EnableOptionsSP();

  // We successfully parsed and validated the options.
  return options_sp;
}

bool RunEnableCommand(CommandInterpreter &interpreter) {
  StreamString command_stream;

  command_stream << "plugin structured-data darwin-log enable";
  auto enable_options = GetGlobalProperties()->GetAutoEnableOptions();
  if (!enable_options.empty()) {
    command_stream << ' ';
    command_stream << enable_options;
  }

  // Run the command.
  CommandReturnObject return_object;
  interpreter.HandleCommand(command_stream.GetData(), eLazyBoolNo,
                            return_object);
  return return_object.Succeeded();
}
}
using namespace sddarwinlog_private;

#pragma mark -
#pragma mark Public static API

// -----------------------------------------------------------------------------
// Public static API
// -----------------------------------------------------------------------------

void StructuredDataDarwinLog::Initialize() {
  RegisterFilterOperations();
  PluginManager::RegisterPlugin(
      GetStaticPluginName(), "Darwin os_log() and os_activity() support",
      &CreateInstance, &DebuggerInitialize, &FilterLaunchInfo);
}

void StructuredDataDarwinLog::Terminate() {
  PluginManager::UnregisterPlugin(&CreateInstance);
}

const ConstString &StructuredDataDarwinLog::GetStaticPluginName() {
  static ConstString s_plugin_name("darwin-log");
  return s_plugin_name;
}

#pragma mark -
#pragma mark PluginInterface API

// -----------------------------------------------------------------------------
// PluginInterface API
// -----------------------------------------------------------------------------

ConstString StructuredDataDarwinLog::GetPluginName() {
  return GetStaticPluginName();
}

uint32_t StructuredDataDarwinLog::GetPluginVersion() { return 1; }

#pragma mark -
#pragma mark StructuredDataPlugin API

// -----------------------------------------------------------------------------
// StructuredDataPlugin API
// -----------------------------------------------------------------------------

bool StructuredDataDarwinLog::SupportsStructuredDataType(
    const ConstString &type_name) {
  return type_name == GetDarwinLogTypeName();
}

void StructuredDataDarwinLog::HandleArrivalOfStructuredData(
    Process &process, const ConstString &type_name,
    const StructuredData::ObjectSP &object_sp) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log) {
    StreamString json_stream;
    if (object_sp)
      object_sp->Dump(json_stream);
    else
      json_stream.PutCString("<null>");
    log->Printf("StructuredDataDarwinLog::%s() called with json: %s",
                __FUNCTION__, json_stream.GetData());
  }

  // Ignore empty structured data.
  if (!object_sp) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() StructuredData object "
                  "is null",
                  __FUNCTION__);
    return;
  }

  // Ignore any data that isn't for us.
  if (type_name != GetDarwinLogTypeName()) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() StructuredData type "
                  "expected to be %s but was %s, ignoring",
                  __FUNCTION__, GetDarwinLogTypeName().AsCString(),
                  type_name.AsCString());
    return;
  }

  // Broadcast the structured data event if we have that enabled.
  // This is the way that the outside world (all clients) get access
  // to this data.  This plugin sets policy as to whether we do that.
  DebuggerSP debugger_sp = process.GetTarget().GetDebugger().shared_from_this();
  auto options_sp = GetGlobalEnableOptions(debugger_sp);
  if (options_sp && options_sp->GetBroadcastEvents()) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() broadcasting event",
                  __FUNCTION__);
    process.BroadcastStructuredData(object_sp, shared_from_this());
  }

  // Later, hang on to a configurable amount of these and allow commands
  // to inspect, including showing backtraces.
}

static void SetErrorWithJSON(Status &error, const char *message,
                             StructuredData::Object &object) {
  if (!message) {
    error.SetErrorString("Internal error: message not set.");
    return;
  }

  StreamString object_stream;
  object.Dump(object_stream);
  object_stream.Flush();

  error.SetErrorStringWithFormat("%s: %s", message, object_stream.GetData());
}

Status StructuredDataDarwinLog::GetDescription(
    const StructuredData::ObjectSP &object_sp, lldb_private::Stream &stream) {
  Status error;

  if (!object_sp) {
    error.SetErrorString("No structured data.");
    return error;
  }

  // Log message payload objects will be dictionaries.
  const StructuredData::Dictionary *dictionary = object_sp->GetAsDictionary();
  if (!dictionary) {
    SetErrorWithJSON(error, "Structured data should have been a dictionary "
                            "but wasn't",
                     *object_sp);
    return error;
  }

  // Validate this is really a message for our plugin.
  ConstString type_name;
  if (!dictionary->GetValueForKeyAsString("type", type_name)) {
    SetErrorWithJSON(error, "Structured data doesn't contain mandatory "
                            "type field",
                     *object_sp);
    return error;
  }

  if (type_name != GetDarwinLogTypeName()) {
    // This is okay - it simply means the data we received is not a log
    // message.  We'll just format it as is.
    object_sp->Dump(stream);
    return error;
  }

  // DarwinLog dictionaries store their data
  // in an array with key name "events".
  StructuredData::Array *events = nullptr;
  if (!dictionary->GetValueForKeyAsArray("events", events) || !events) {
    SetErrorWithJSON(error, "Log structured data is missing mandatory "
                            "'events' field, expected to be an array",
                     *object_sp);
    return error;
  }

  events->ForEach(
      [&stream, &error, &object_sp, this](StructuredData::Object *object) {
        if (!object) {
          // Invalid.  Stop iterating.
          SetErrorWithJSON(error, "Log event entry is null", *object_sp);
          return false;
        }

        auto event = object->GetAsDictionary();
        if (!event) {
          // Invalid, stop iterating.
          SetErrorWithJSON(error, "Log event is not a dictionary", *object_sp);
          return false;
        }

        // If we haven't already grabbed the first timestamp
        // value, do that now.
        if (!m_recorded_first_timestamp) {
          uint64_t timestamp = 0;
          if (event->GetValueForKeyAsInteger("timestamp", timestamp)) {
            m_first_timestamp_seen = timestamp;
            m_recorded_first_timestamp = true;
          }
        }

        HandleDisplayOfEvent(*event, stream);
        return true;
      });

  stream.Flush();
  return error;
}

bool StructuredDataDarwinLog::GetEnabled(const ConstString &type_name) const {
  if (type_name == GetStaticPluginName())
    return m_is_enabled;
  else
    return false;
}

void StructuredDataDarwinLog::SetEnabled(bool enabled) {
  m_is_enabled = enabled;
}

void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
                                             ModuleList &module_list) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log)
    log->Printf("StructuredDataDarwinLog::%s called (process uid %u)",
                __FUNCTION__, process.GetUniqueID());

  // Check if we should enable the darwin log support on startup/attach.
  if (!GetGlobalProperties()->GetEnableOnStartup() &&
      !s_is_explicitly_enabled) {
    // We're neither auto-enabled or explicitly enabled, so we shouldn't
    // try to enable here.
    if (log)
      log->Printf("StructuredDataDarwinLog::%s not applicable, we're not "
                  "enabled (process uid %u)",
                  __FUNCTION__, process.GetUniqueID());
    return;
  }

  // If we already added the breakpoint, we've got nothing left to do.
  {
    std::lock_guard<std::mutex> locker(m_added_breakpoint_mutex);
    if (m_added_breakpoint) {
      if (log)
        log->Printf("StructuredDataDarwinLog::%s process uid %u's "
                    "post-libtrace-init breakpoint is already set",
                    __FUNCTION__, process.GetUniqueID());
      return;
    }
  }

  // The logging support module name, specifies the name of
  // the image name that must be loaded into the debugged process before
  // we can try to enable logging.
  const char *logging_module_cstr =
      GetGlobalProperties()->GetLoggingModuleName();
  if (!logging_module_cstr || (logging_module_cstr[0] == 0)) {
    // We need this.  Bail.
    if (log)
      log->Printf("StructuredDataDarwinLog::%s no logging module name "
                  "specified, we don't know where to set a breakpoint "
                  "(process uid %u)",
                  __FUNCTION__, process.GetUniqueID());
    return;
  }

  const ConstString logging_module_name = ConstString(logging_module_cstr);

  // We need to see libtrace in the list of modules before we can enable
  // tracing for the target process.
  bool found_logging_support_module = false;
  for (size_t i = 0; i < module_list.GetSize(); ++i) {
    auto module_sp = module_list.GetModuleAtIndex(i);
    if (!module_sp)
      continue;

    auto &file_spec = module_sp->GetFileSpec();
    found_logging_support_module =
        (file_spec.GetLastPathComponent() == logging_module_name);
    if (found_logging_support_module)
      break;
  }

  if (!found_logging_support_module) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s logging module %s "
                  "has not yet been loaded, can't set a breakpoint "
                  "yet (process uid %u)",
                  __FUNCTION__, logging_module_name.AsCString(),
                  process.GetUniqueID());
    return;
  }

  // Time to enqueue the breakpoint so we can wait for logging support
  // to be initialized before we try to tap the libtrace stream.
  AddInitCompletionHook(process);
  if (log)
    log->Printf("StructuredDataDarwinLog::%s post-init hook breakpoint "
                "set for logging module %s (process uid %u)",
                __FUNCTION__, logging_module_name.AsCString(),
                process.GetUniqueID());

  // We need to try the enable here as well, which will succeed
  // in the event that we're attaching to (rather than launching) the
  // process and the process is already past initialization time.  In that
  // case, the completion breakpoint will never get hit and therefore won't
  // start that way.  It doesn't hurt much beyond a bit of bandwidth
  // if we end up doing this twice.  It hurts much more if we don't get
  // the logging enabled when the user expects it.
  EnableNow();
}

// -----------------------------------------------------------------------------
// public destructor
// -----------------------------------------------------------------------------

StructuredDataDarwinLog::~StructuredDataDarwinLog() {
  if (m_breakpoint_id != LLDB_INVALID_BREAK_ID) {
    ProcessSP process_sp(GetProcess());
    if (process_sp) {
      process_sp->GetTarget().RemoveBreakpointByID(m_breakpoint_id);
      m_breakpoint_id = LLDB_INVALID_BREAK_ID;
    }
  }
}

#pragma mark -
#pragma mark Private instance methods

// -----------------------------------------------------------------------------
// Private constructors
// -----------------------------------------------------------------------------

StructuredDataDarwinLog::StructuredDataDarwinLog(const ProcessWP &process_wp)
    : StructuredDataPlugin(process_wp), m_recorded_first_timestamp(false),
      m_first_timestamp_seen(0), m_is_enabled(false),
      m_added_breakpoint_mutex(), m_added_breakpoint(),
      m_breakpoint_id(LLDB_INVALID_BREAK_ID) {}

// -----------------------------------------------------------------------------
// Private static methods
// -----------------------------------------------------------------------------

StructuredDataPluginSP
StructuredDataDarwinLog::CreateInstance(Process &process) {
  // Currently only Apple targets support the os_log/os_activity
  // protocol.
  if (process.GetTarget().GetArchitecture().GetTriple().getVendor() ==
      llvm::Triple::VendorType::Apple) {
    auto process_wp = ProcessWP(process.shared_from_this());
    return StructuredDataPluginSP(new StructuredDataDarwinLog(process_wp));
  } else {
    return StructuredDataPluginSP();
  }
}

void StructuredDataDarwinLog::DebuggerInitialize(Debugger &debugger) {
  // Setup parent class first.
  StructuredDataPlugin::InitializeBasePluginForDebugger(debugger);

  // Get parent command.
  auto &interpreter = debugger.GetCommandInterpreter();
  llvm::StringRef parent_command_text = "plugin structured-data";
  auto parent_command =
      interpreter.GetCommandObjectForCommand(parent_command_text);
  if (!parent_command) {
    // Ut oh, parent failed to create parent command.
    // TODO log
    return;
  }

  auto command_name = "darwin-log";
  auto command_sp = CommandObjectSP(new BaseCommand(interpreter));
  bool result = parent_command->LoadSubCommand(command_name, command_sp);
  if (!result) {
    // TODO log it once we setup structured data logging
  }

  if (!PluginManager::GetSettingForPlatformPlugin(
          debugger, StructuredDataDarwinLogProperties::GetSettingName())) {
    const bool is_global_setting = true;
    PluginManager::CreateSettingForStructuredDataPlugin(
        debugger, GetGlobalProperties()->GetValueProperties(),
        ConstString("Properties for the darwin-log"
                    " plug-in."),
        is_global_setting);
  }
}

Status StructuredDataDarwinLog::FilterLaunchInfo(ProcessLaunchInfo &launch_info,
                                                 Target *target) {
  Status error;

  // If we're not debugging this launched process, there's nothing for us
  // to do here.
  if (!launch_info.GetFlags().AnySet(eLaunchFlagDebug))
    return error;

  // Darwin os_log() support automatically adds debug-level and info-level
  // messages when a debugger is attached to a process.  However, with
  // integrated suppport for debugging built into the command-line LLDB,
  // the user may specifically set to *not* include debug-level and info-level
  // content.  When the user is using the integrated log support, we want
  // to put the kabosh on that automatic adding of info and debug level.
  // This is done by adding an environment variable to the process on launch.
  // (This also means it is not possible to suppress this behavior if
  // attaching to an already-running app).
  // Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));

  // If the target architecture is not one that supports DarwinLog, we have
  // nothing to do here.
  auto &triple = target ? target->GetArchitecture().GetTriple()
                        : launch_info.GetArchitecture().GetTriple();
  if (triple.getVendor() != llvm::Triple::Apple) {
    return error;
  }

  // If DarwinLog is not enabled (either by explicit user command or via
  // the auto-enable option), then we have nothing to do.
  if (!GetGlobalProperties()->GetEnableOnStartup() &&
      !s_is_explicitly_enabled) {
    // Nothing to do, DarwinLog is not enabled.
    return error;
  }

  // If we don't have parsed configuration info, that implies we have
  // enable-on-startup set up, but we haven't yet attempted to run the
  // enable command.
  if (!target) {
    // We really can't do this without a target.  We need to be able
    // to get to the debugger to get the proper options to do this right.
    // TODO log.
    error.SetErrorString("requires a target to auto-enable DarwinLog.");
    return error;
  }

  DebuggerSP debugger_sp = target->GetDebugger().shared_from_this();
  auto options_sp = GetGlobalEnableOptions(debugger_sp);
  if (!options_sp && debugger_sp) {
    options_sp = ParseAutoEnableOptions(error, *debugger_sp.get());
    if (!options_sp || !error.Success())
      return error;

    // We already parsed the options, save them now so we don't generate
    // them again until the user runs the command manually.
    SetGlobalEnableOptions(debugger_sp, options_sp);
  }

  auto &env_vars = launch_info.GetEnvironmentEntries();
  if (!options_sp->GetEchoToStdErr()) {
    // The user doesn't want to see os_log/NSLog messages echo to stderr.
    // That mechanism is entirely separate from the DarwinLog support.
    // By default we don't want to get it via stderr, because that would
    // be in duplicate of the explicit log support here.

    // Here we need to strip out any OS_ACTIVITY_DT_MODE setting to prevent
    // echoing of os_log()/NSLog() to stderr in the target program.
    size_t argument_index;
    if (env_vars.ContainsEnvironmentVariable(
            llvm::StringRef("OS_ACTIVITY_DT_MODE"), &argument_index))
      env_vars.DeleteArgumentAtIndex(argument_index);

    // We will also set the env var that tells any downstream launcher
    // from adding OS_ACTIVITY_DT_MODE.
    env_vars.AddOrReplaceEnvironmentVariable(
        llvm::StringRef("IDE_DISABLED_OS_ACTIVITY_DT_MODE"),
        llvm::StringRef("1"));
  }

  // Set the OS_ACTIVITY_MODE env var appropriately to enable/disable
  // debug and info level messages.
  const char *env_var_value;
  if (options_sp->GetIncludeDebugLevel())
    env_var_value = "debug";
  else if (options_sp->GetIncludeInfoLevel())
    env_var_value = "info";
  else
    env_var_value = "default";

  if (env_var_value) {
    launch_info.GetEnvironmentEntries().AddOrReplaceEnvironmentVariable(
        llvm::StringRef("OS_ACTIVITY_MODE"), llvm::StringRef(env_var_value));
  }

  return error;
}

bool StructuredDataDarwinLog::InitCompletionHookCallback(
    void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
    lldb::user_id_t break_loc_id) {
  // We hit the init function.  We now want to enqueue our new thread plan,
  // which will in turn enqueue a StepOut thread plan. When the StepOut
  // finishes and control returns to our new thread plan, that is the time
  // when we can execute our logic to enable the logging support.

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log)
    log->Printf("StructuredDataDarwinLog::%s() called", __FUNCTION__);

  // Get the current thread.
  if (!context) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() warning: no context, "
                  "ignoring",
                  __FUNCTION__);
    return false;
  }

  // Get the plugin from the process.
  auto process_sp = context->exe_ctx_ref.GetProcessSP();
  if (!process_sp) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() warning: invalid "
                  "process in context, ignoring",
                  __FUNCTION__);
    return false;
  }
  if (log)
    log->Printf("StructuredDataDarwinLog::%s() call is for process uid %d",
                __FUNCTION__, process_sp->GetUniqueID());

  auto plugin_sp = process_sp->GetStructuredDataPlugin(GetDarwinLogTypeName());
  if (!plugin_sp) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() warning: no plugin for "
                  "feature %s in process uid %u",
                  __FUNCTION__, GetDarwinLogTypeName().AsCString(),
                  process_sp->GetUniqueID());
    return false;
  }

  // Create the callback for when the thread plan completes.
  bool called_enable_method = false;
  const auto process_uid = process_sp->GetUniqueID();

  std::weak_ptr<StructuredDataPlugin> plugin_wp(plugin_sp);
  ThreadPlanCallOnFunctionExit::Callback callback =
      [plugin_wp, &called_enable_method, log, process_uid]() {
        if (log)
          log->Printf("StructuredDataDarwinLog::post-init callback: "
                      "called (process uid %u)",
                      process_uid);

        auto strong_plugin_sp = plugin_wp.lock();
        if (!strong_plugin_sp) {
          if (log)
            log->Printf("StructuredDataDarwinLog::post-init callback: "
                        "plugin no longer exists, ignoring (process "
                        "uid %u)",
                        process_uid);
          return;
        }
        // Make sure we only call it once, just in case the
        // thread plan hits the breakpoint twice.
        if (!called_enable_method) {
          if (log)
            log->Printf("StructuredDataDarwinLog::post-init callback: "
                        "calling EnableNow() (process uid %u)",
                        process_uid);
          static_cast<StructuredDataDarwinLog *>(strong_plugin_sp.get())
              ->EnableNow();
          called_enable_method = true;
        } else {
          // Our breakpoint was hit more than once.  Unexpected but
          // no harm done.  Log it.
          if (log)
            log->Printf("StructuredDataDarwinLog::post-init callback: "
                        "skipping EnableNow(), already called by "
                        "callback [we hit this more than once] "
                        "(process uid %u)",
                        process_uid);
        }
      };

  // Grab the current thread.
  auto thread_sp = context->exe_ctx_ref.GetThreadSP();
  if (!thread_sp) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() warning: failed to "
                  "retrieve the current thread from the execution "
                  "context, nowhere to run the thread plan (process uid "
                  "%u)",
                  __FUNCTION__, process_sp->GetUniqueID());
    return false;
  }

  // Queue the thread plan.
  auto thread_plan_sp = ThreadPlanSP(
      new ThreadPlanCallOnFunctionExit(*thread_sp.get(), callback));
  const bool abort_other_plans = false;
  thread_sp->QueueThreadPlan(thread_plan_sp, abort_other_plans);
  if (log)
    log->Printf("StructuredDataDarwinLog::%s() queuing thread plan on "
                "trace library init method entry (process uid %u)",
                __FUNCTION__, process_sp->GetUniqueID());

  // We return false here to indicate that it isn't a public stop.
  return false;
}

void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log)
    log->Printf("StructuredDataDarwinLog::%s() called (process uid %u)",
                __FUNCTION__, process.GetUniqueID());

  // Make sure we haven't already done this.
  {
    std::lock_guard<std::mutex> locker(m_added_breakpoint_mutex);
    if (m_added_breakpoint) {
      if (log)
        log->Printf("StructuredDataDarwinLog::%s() ignoring request, "
                    "breakpoint already set (process uid %u)",
                    __FUNCTION__, process.GetUniqueID());
      return;
    }

    // We're about to do this, don't let anybody else try to do it.
    m_added_breakpoint = true;
  }

  // Set a breakpoint for the process that will kick in when libtrace
  // has finished its initialization.
  Target &target = process.GetTarget();

  // Build up the module list.
  FileSpecList module_spec_list;
  auto module_file_spec =
      FileSpec(GetGlobalProperties()->GetLoggingModuleName(), false);
  module_spec_list.Append(module_file_spec);

  // We aren't specifying a source file set.
  FileSpecList *source_spec_list = nullptr;

  const char *func_name = "_libtrace_init";
  const lldb::addr_t offset = 0;
  const LazyBool skip_prologue = eLazyBoolCalculate;
  // This is an internal breakpoint - the user shouldn't see it.
  const bool internal = true;
  const bool hardware = false;

  auto breakpoint_sp = target.CreateBreakpoint(
      &module_spec_list, source_spec_list, func_name, eFunctionNameTypeFull,
      eLanguageTypeC, offset, skip_prologue, internal, hardware);
  if (!breakpoint_sp) {
    // Huh?  Bail here.
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() failed to set "
                  "breakpoint in module %s, function %s (process uid %u)",
                  __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(),
                  func_name, process.GetUniqueID());
    return;
  }

  // Set our callback.
  breakpoint_sp->SetCallback(InitCompletionHookCallback, nullptr);
  m_breakpoint_id = breakpoint_sp->GetID();
  if (log)
    log->Printf("StructuredDataDarwinLog::%s() breakpoint set in module %s,"
                "function %s (process uid %u)",
                __FUNCTION__, GetGlobalProperties()->GetLoggingModuleName(),
                func_name, process.GetUniqueID());
}

void StructuredDataDarwinLog::DumpTimestamp(Stream &stream,
                                            uint64_t timestamp) {
  const uint64_t delta_nanos = timestamp - m_first_timestamp_seen;

  const uint64_t hours = delta_nanos / NANOS_PER_HOUR;
  uint64_t nanos_remaining = delta_nanos % NANOS_PER_HOUR;

  const uint64_t minutes = nanos_remaining / NANOS_PER_MINUTE;
  nanos_remaining = nanos_remaining % NANOS_PER_MINUTE;

  const uint64_t seconds = nanos_remaining / NANOS_PER_SECOND;
  nanos_remaining = nanos_remaining % NANOS_PER_SECOND;

  stream.Printf("%02" PRIu64 ":%02" PRIu64 ":%02" PRIu64 ".%09" PRIu64, hours,
                minutes, seconds, nanos_remaining);
}

size_t
StructuredDataDarwinLog::DumpHeader(Stream &output_stream,
                                    const StructuredData::Dictionary &event) {
  StreamString stream;

  ProcessSP process_sp = GetProcess();
  if (!process_sp) {
    // TODO log
    return 0;
  }

  DebuggerSP debugger_sp =
      process_sp->GetTarget().GetDebugger().shared_from_this();
  if (!debugger_sp) {
    // TODO log
    return 0;
  }

  auto options_sp = GetGlobalEnableOptions(debugger_sp);
  if (!options_sp) {
    // TODO log
    return 0;
  }

  // Check if we should even display a header.
  if (!options_sp->GetDisplayAnyHeaderFields())
    return 0;

  stream.PutChar('[');

  int header_count = 0;
  if (options_sp->GetDisplayTimestampRelative()) {
    uint64_t timestamp = 0;
    if (event.GetValueForKeyAsInteger("timestamp", timestamp)) {
      DumpTimestamp(stream, timestamp);
      ++header_count;
    }
  }

  if (options_sp->GetDisplayActivityChain()) {
    llvm::StringRef activity_chain;
    if (event.GetValueForKeyAsString("activity-chain", activity_chain) &&
        !activity_chain.empty()) {
      if (header_count > 0)
        stream.PutChar(',');

// Switch over to the #if 0 branch once we figure out
// how we want to present settings for the tri-state of
// no-activity, activity (most derived only), or activity-chain.
#if 1
      // Display the activity chain, from parent-most to child-most
      // activity, separated by a colon (:).
      stream.PutCString("activity-chain=");
      stream.PutCString(activity_chain);
#else
      if (GetGlobalProperties()->GetDisplayActivityChain()) {
        // Display the activity chain, from parent-most to child-most
        // activity, separated by a colon (:).
        stream.PutCString("activity-chain=");
        stream.PutCString(activity_chain.c_str());
      } else {
        // We're only displaying the child-most activity.
        stream.PutCString("activity=");
        auto pos = activity_chain.find_last_of(':');
        if (pos == std::string::npos) {
          // The activity chain only has one level, use the whole
          // thing.
          stream.PutCString(activity_chain.c_str());
        } else {
          // Display everything after the final ':'.
          stream.PutCString(activity_chain.substr(pos + 1).c_str());
        }
      }
#endif
      ++header_count;
    }
  }

  if (options_sp->GetDisplaySubsystem()) {
    llvm::StringRef subsystem;
    if (event.GetValueForKeyAsString("subsystem", subsystem) &&
        !subsystem.empty()) {
      if (header_count > 0)
        stream.PutChar(',');
      stream.PutCString("subsystem=");
      stream.PutCString(subsystem);
      ++header_count;
    }
  }

  if (options_sp->GetDisplayCategory()) {
    llvm::StringRef category;
    if (event.GetValueForKeyAsString("category", category) &&
        !category.empty()) {
      if (header_count > 0)
        stream.PutChar(',');
      stream.PutCString("category=");
      stream.PutCString(category);
      ++header_count;
    }
  }
  stream.PutCString("] ");

  output_stream.PutCString(stream.GetString());

  return stream.GetSize();
}

size_t StructuredDataDarwinLog::HandleDisplayOfEvent(
    const StructuredData::Dictionary &event, Stream &stream) {
  // Check the type of the event.
  ConstString event_type;
  if (!event.GetValueForKeyAsString("type", event_type)) {
    // Hmm, we expected to get events that describe
    // what they are.  Continue anyway.
    return 0;
  }

  if (event_type != GetLogEventType())
    return 0;

  size_t total_bytes = 0;

  // Grab the message content.
  llvm::StringRef message;
  if (!event.GetValueForKeyAsString("message", message))
    return true;

  // Display the log entry.
  const auto len = message.size();

  total_bytes += DumpHeader(stream, event);

  stream.Write(message.data(), len);
  total_bytes += len;

  // Add an end of line.
  stream.PutChar('\n');
  total_bytes += sizeof(char);

  return total_bytes;
}

void StructuredDataDarwinLog::EnableNow() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (log)
    log->Printf("StructuredDataDarwinLog::%s() called", __FUNCTION__);

  // Run the enable command.
  auto process_sp = GetProcess();
  if (!process_sp) {
    // Nothing to do.
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() warning: failed to get "
                  "valid process, skipping",
                  __FUNCTION__);
    return;
  }
  if (log)
    log->Printf("StructuredDataDarwinLog::%s() call is for process uid %u",
                __FUNCTION__, process_sp->GetUniqueID());

  // If we have configuration data, we can directly enable it now.
  // Otherwise, we need to run through the command interpreter to parse
  // the auto-run options (which is the only way we get here without having
  // already-parsed configuration data).
  DebuggerSP debugger_sp =
      process_sp->GetTarget().GetDebugger().shared_from_this();
  if (!debugger_sp) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() warning: failed to get "
                  "debugger shared pointer, skipping (process uid %u)",
                  __FUNCTION__, process_sp->GetUniqueID());
    return;
  }

  auto options_sp = GetGlobalEnableOptions(debugger_sp);
  if (!options_sp) {
    // We haven't run the enable command yet.  Just do that now, it'll
    // take care of the rest.
    auto &interpreter = debugger_sp->GetCommandInterpreter();
    const bool success = RunEnableCommand(interpreter);
    if (log) {
      if (success)
        log->Printf("StructuredDataDarwinLog::%s() ran enable command "
                    "successfully for (process uid %u)",
                    __FUNCTION__, process_sp->GetUniqueID());
      else
        log->Printf("StructuredDataDarwinLog::%s() error: running "
                    "enable command failed (process uid %u)",
                    __FUNCTION__, process_sp->GetUniqueID());
    }
    // Report failures to the debugger error stream.
    auto error_stream_sp = debugger_sp->GetAsyncErrorStream();
    if (error_stream_sp) {
      error_stream_sp->Printf("failed to configure DarwinLog "
                              "support\n");
      error_stream_sp->Flush();
    }
    return;
  }

  // We've previously been enabled. We will re-enable now with the
  // previously specified options.
  auto config_sp = options_sp->BuildConfigurationData(true);
  if (!config_sp) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() warning: failed to "
                  "build configuration data for enable options, skipping "
                  "(process uid %u)",
                  __FUNCTION__, process_sp->GetUniqueID());
    return;
  }

  // We can run it directly.
  // Send configuration to the feature by way of the process.
  const Status error =
      process_sp->ConfigureStructuredData(GetDarwinLogTypeName(), config_sp);

  // Report results.
  if (!error.Success()) {
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() "
                  "ConfigureStructuredData() call failed "
                  "(process uid %u): %s",
                  __FUNCTION__, process_sp->GetUniqueID(), error.AsCString());
    auto error_stream_sp = debugger_sp->GetAsyncErrorStream();
    if (error_stream_sp) {
      error_stream_sp->Printf("failed to configure DarwinLog "
                              "support: %s\n",
                              error.AsCString());
      error_stream_sp->Flush();
    }
    m_is_enabled = false;
  } else {
    m_is_enabled = true;
    if (log)
      log->Printf("StructuredDataDarwinLog::%s() success via direct "
                  "configuration (process uid %u)",
                  __FUNCTION__, process_sp->GetUniqueID());
  }
}
