//===-- StructuredDataDarwinLog.cpp ---------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "StructuredDataDarwinLog.h"

#include <cstring>

#include <memory>
#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/OptionArgParser.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/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"

#include "llvm/ADT/StringMap.h"

#define DARWIN_LOG_TYPE_VALUE "DarwinLog"

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(StructuredDataDarwinLog)

#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

#define LLDB_PROPERTIES_darwinlog
#include "StructuredDataDarwinLogProperties.inc"

enum {
#define LLDB_PROPERTIES_darwinlog
#include "StructuredDataDarwinLogPropertiesEnum.inc"
};

class StructuredDataDarwinLogProperties : public Properties {
public:
  static llvm::StringRef GetSettingName() {
    static constexpr llvm::StringLiteral g_setting_name("darwin-log");
    return g_setting_name;
  }

  StructuredDataDarwinLogProperties() : Properties() {
    m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
    m_collection_sp->Initialize(g_darwinlog_properties_def);
  }

  ~StructuredDataDarwinLogProperties() override = default;

  bool GetEnableOnStartup() const {
    const uint32_t idx = ePropertyEnableOnStartup;
    return GetPropertyAtIndexAs<bool>(
        idx, g_darwinlog_properties[idx].default_uint_value != 0);
  }

  llvm::StringRef GetAutoEnableOptions() const {
    const uint32_t idx = ePropertyAutoEnableOptions;
    return GetPropertyAtIndexAs<llvm::StringRef>(
        idx, g_darwinlog_properties[idx].default_cstr_value);
  }

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

static StructuredDataDarwinLogProperties &GetGlobalProperties() {
  static StructuredDataDarwinLogProperties g_settings;
  return g_settings;
}

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 implementing 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 llvm::StringRef GetDarwinLogTypeName() {
  static constexpr llvm::StringLiteral s_key_name("DarwinLog");
  return s_key_name;
}

static llvm::StringRef GetLogEventType() {
  static constexpr llvm::StringLiteral s_event_type("log");
  return s_event_type;
}

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

class FilterRule {
public:
  virtual ~FilterRule() = default;

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

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

  static FilterRuleSP CreateRule(bool match_accepts, size_t attribute,
                                 llvm::StringRef 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 = Status::FromErrorStringWithFormatv(
          "unknown filter operation \"{0}\"", operation);
      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());

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

    return StructuredData::ObjectSP(dict_p);
  }

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

  llvm::StringRef GetOperationType() const { return m_operation; }

protected:
  FilterRule(bool accept, size_t attribute_index, llvm::StringRef 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 = llvm::StringMap<OperationCreationFunc>;

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

  const bool m_accept;
  const size_t m_attribute_index;
  // The lifetime of m_operation should be static.
  const llvm::StringRef 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 = Status::FromErrorString("regex filter type requires a regex "
                                      "argument");
      return FilterRuleSP();
    }

    // Instantiate the regex so we can report any errors.
    auto regex = RegularExpression(op_arg);
    if (llvm::Error err = regex.GetError()) {
      error = Status::FromError(std::move(err));
      return FilterRuleSP();
    }

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

  static llvm::StringRef StaticGetOperation() {
    static constexpr llvm::StringLiteral 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 = Status::FromErrorString("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 llvm::StringRef StaticGetOperation() {
    static constexpr llvm::StringLiteral 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 constexpr 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, {}, 0, eArgTypeNone,
     "Specifies log messages from other related processes should be "
     "included."},
    {LLDB_OPT_SET_ALL, false, "debug", 'd', OptionParser::eNoArgument, 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,
     {}, 0, eArgTypeNone,
     "Specifies info-level log messages should be included."},
    {LLDB_OPT_SET_ALL, false, "filter", 'f', OptionParser::eRequiredArgument,
     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, {}, 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, {}, 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, {}, 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, {}, 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, {}, 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, {}, 0, eArgTypeNone,
     "Include the subsystem in the message header when displaying "
     "a log message."},
    {LLDB_OPT_SET_ALL, false, "category", 'c', OptionParser::eNoArgument,
     nullptr, {}, 0, eArgTypeNone,
     "Include the category in the message header when displaying "
     "a log message."},
    {LLDB_OPT_SET_ALL, false, "activity-chain", 'C', OptionParser::eNoArgument,
     nullptr, {}, 0, eArgTypeNone,
     "Include the activity parent-child chain in 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, {}, 0, eArgTypeNone,
     "Shortcut to specify that all header fields should be displayed."}};

class EnableOptions : public Options {
public:
  EnableOptions()
      : Options(),
        m_filter_fall_through_accepts(DEFAULT_FILTER_FALLTHROUGH_ACCEPTS),
        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 =
          OptionArgParser::ToBoolean(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 = OptionArgParser::ToBoolean(option_arg, false, nullptr);
      break;

    case 'f':
      return ParseFilterRule(option_arg);

    case 'i':
      m_include_info_level = true;
      break;

    case 'l':
      m_live_stream = OptionArgParser::ToBoolean(option_arg, false, nullptr);
      break;

    case 'n':
      m_filter_fall_through_accepts =
          OptionArgParser::ToBoolean(option_arg, true, nullptr);
      break;

    case 'r':
      m_display_timestamp_relative = true;
      break;

    case 's':
      m_display_subsystem = true;
      break;

    default:
      error = Status::FromErrorStringWithFormat("unsupported option '%c'",
                                                short_option);
    }
    return error;
  }

  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
    return llvm::ArrayRef(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 = std::make_shared<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, implies 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 = std::make_shared<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 = Status::FromErrorString("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 = Status::FromErrorStringWithFormat("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 = Status::FromErrorString(
          "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 = Status::FromErrorStringWithFormat("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 =
          Status::FromErrorStringWithFormat("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, operation,
        std::string(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 = false;
  bool m_include_info_level = false;
  bool m_include_any_process = false;
  bool m_filter_fall_through_accepts;
  bool m_echo_to_stderr = false;
  bool m_display_timestamp_relative = false;
  bool m_display_subsystem = false;
  bool m_display_category = false;
  bool m_display_activity_chain = false;
  bool m_broadcast_events = true;
  bool m_live_stream = true;
  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());
  }

  void 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 = GetTarget();

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

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

    // 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");
    }
    StructuredDataDarwinLog &plugin =
        *static_cast<StructuredDataDarwinLog *>(plugin_sp.get());

    if (m_enable) {
      // 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);
    }

    // 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());
      // Our configuration failed, so we're definitely disabled.
      plugin.SetEnabled(false);
    } else {
      result.SetStatus(eReturnStatusSuccessFinishNoResult);
      // Our configuration succeeded, so we're enabled/disabled per whichever
      // one this command is setup to do.
      plugin.SetEnabled(m_enable);
    }
  }

  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:
  void 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 = GetTarget();
    auto process_sp = target.GetProcessSP();
    if (!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");
      const bool enabled =
          plugin_sp ? plugin_sp->GetEnabled(
                          StructuredDataDarwinLog::GetStaticPluginName())
                    : 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;
    }

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

/// 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) {
  Log *log = GetLog(LLDBLog::Process);
  // 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);

  // Parse the arguments.
  auto options_property_sp =
      debugger.GetPropertyValue(nullptr,
                                "plugin.structured-data.darwin-log."
                                "auto-enable-options",
                                error);
  if (!error.Success())
    return EnableOptionsSP();
  if (!options_property_sp) {
    error = Status::FromErrorString("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();
  }

  bool require_validation = false;
  llvm::Expected<Args> args_or =
      options_sp->Parse(args, &exe_ctx, PlatformSP(), require_validation);
  if (!args_or) {
    LLDB_LOG_ERROR(
        log, args_or.takeError(),
        "Parsing plugin.structured-data.darwin-log.auto-enable-options value "
        "failed: {0}");
    return EnableOptionsSP();
  }

  if (llvm::Error error = options_sp->VerifyOptions()) {
    LLDB_LOG_ERROR(
        log, std::move(error),
        "Parsing plugin.structured-data.darwin-log.auto-enable-options value "
        "failed: {0}");
    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.GetDebugger().GetUseColor());
  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);
}

#pragma mark -
#pragma mark StructuredDataPlugin API

// StructuredDataPlugin API

bool StructuredDataDarwinLog::SupportsStructuredDataType(
    llvm::StringRef type_name) {
  return type_name == GetDarwinLogTypeName();
}

void StructuredDataDarwinLog::HandleArrivalOfStructuredData(
    Process &process, llvm::StringRef type_name,
    const StructuredData::ObjectSP &object_sp) {
  Log *log = GetLog(LLDBLog::Process);
  if (log) {
    StreamString json_stream;
    if (object_sp)
      object_sp->Dump(json_stream);
    else
      json_stream.PutCString("<null>");
    LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called with json: %s",
              __FUNCTION__, json_stream.GetData());
  }

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

  // Ignore any data that isn't for us.
  if (type_name != GetDarwinLogTypeName()) {
    LLDB_LOG(log,
             "StructuredData type expected to be {0} but was {1}, ignoring",
             GetDarwinLogTypeName(), type_name);
    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()) {
    LLDB_LOGF(log, "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 = Status::FromErrorString("Internal error: message not set.");
    return;
  }

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

  error = Status::FromErrorStringWithFormat("%s: %s", message,
                                            object_stream.GetData());
}

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

  if (!object_sp) {
    error = Status::FromErrorString("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.
  llvm::StringRef 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(llvm::StringRef type_name) const {
  if (type_name == GetStaticPluginName())
    return m_is_enabled;
  return false;
}

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

void StructuredDataDarwinLog::ModulesDidLoad(Process &process,
                                             ModuleList &module_list) {
  Log *log = GetLog(LLDBLog::Process);
  LLDB_LOGF(log, "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.
    LLDB_LOGF(log,
              "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) {
      LLDB_LOGF(log,
                "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.
    LLDB_LOGF(log,
              "StructuredDataDarwinLog::%s no logging module name "
              "specified, we don't know where to set a breakpoint "
              "(process uid %u)",
              __FUNCTION__, process.GetUniqueID());
    return;
  }

  // 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.GetFilename() == logging_module_cstr);
    if (found_logging_support_module)
      break;
  }

  if (!found_logging_support_module) {
    LLDB_LOGF(log,
              "StructuredDataDarwinLog::%s logging module %s "
              "has not yet been loaded, can't set a breakpoint "
              "yet (process uid %u)",
              __FUNCTION__, logging_module_cstr, 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);
  LLDB_LOGF(log,
            "StructuredDataDarwinLog::%s post-init hook breakpoint "
            "set for logging module %s (process uid %u)",
            __FUNCTION__, logging_module_cstr, 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(),
        "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 support 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 = GetLog(LLDBLog::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 =
        Status::FromErrorString("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);
  }

  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.
    launch_info.GetEnvironment().erase("OS_ACTIVITY_DT_MODE");

    // We will also set the env var that tells any downstream launcher from
    // adding OS_ACTIVITY_DT_MODE.
    launch_info.GetEnvironment()["IDE_DISABLED_OS_ACTIVITY_DT_MODE"] = "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";

  launch_info.GetEnvironment()["OS_ACTIVITY_MODE"] = 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 = GetLog(LLDBLog::Process);
  LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called", __FUNCTION__);

  // Get the current thread.
  if (!context) {
    LLDB_LOGF(log,
              "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) {
    LLDB_LOGF(log,
              "StructuredDataDarwinLog::%s() warning: invalid "
              "process in context, ignoring",
              __FUNCTION__);
    return false;
  }
  LLDB_LOGF(log, "StructuredDataDarwinLog::%s() call is for process uid %d",
            __FUNCTION__, process_sp->GetUniqueID());

  auto plugin_sp = process_sp->GetStructuredDataPlugin(GetDarwinLogTypeName());
  if (!plugin_sp) {
    LLDB_LOG(log, "warning: no plugin for feature {0} in process uid {1}",
             GetDarwinLogTypeName(), 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]() {
        LLDB_LOGF(log,
                  "StructuredDataDarwinLog::post-init callback: "
                  "called (process uid %u)",
                  process_uid);

        auto strong_plugin_sp = plugin_wp.lock();
        if (!strong_plugin_sp) {
          LLDB_LOGF(log,
                    "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) {
          LLDB_LOGF(log,
                    "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.
          LLDB_LOGF(log,
                    "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) {
    LLDB_LOGF(log,
              "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, callback));
  const bool abort_other_plans = false;
  thread_sp->QueueThreadPlan(thread_plan_sp, abort_other_plans);
  LLDB_LOGF(log,
            "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 = GetLog(LLDBLog::Process);
  LLDB_LOGF(log, "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) {
      LLDB_LOGF(log,
                "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());
  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 bool offset_is_insn_count = false;
  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, offset_is_insn_count, skip_prologue, internal,
      hardware);
  if (!breakpoint_sp) {
    // Huh?  Bail here.
    LLDB_LOGF(log,
              "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();
  LLDB_LOGF(log,
            "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(',');

      // Display the activity chain, from parent-most to child-most activity,
      // separated by a colon (:).
      stream.PutCString("activity-chain=");
      stream.PutCString(activity_chain);
      ++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.
  llvm::StringRef 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 = GetLog(LLDBLog::Process);
  LLDB_LOGF(log, "StructuredDataDarwinLog::%s() called", __FUNCTION__);

  // Run the enable command.
  auto process_sp = GetProcess();
  if (!process_sp) {
    // Nothing to do.
    LLDB_LOGF(log,
              "StructuredDataDarwinLog::%s() warning: failed to get "
              "valid process, skipping",
              __FUNCTION__);
    return;
  }
  LLDB_LOGF(log, "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) {
    LLDB_LOGF(log,
              "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)
        LLDB_LOGF(log,
                  "StructuredDataDarwinLog::%s() ran enable command "
                  "successfully for (process uid %u)",
                  __FUNCTION__, process_sp->GetUniqueID());
      else
        LLDB_LOGF(log,
                  "StructuredDataDarwinLog::%s() error: running "
                  "enable command failed (process uid %u)",
                  __FUNCTION__, process_sp->GetUniqueID());
    }
    Debugger::ReportError("failed to configure DarwinLog support",
                          debugger_sp->GetID());
    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) {
    LLDB_LOGF(log,
              "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()) {
    LLDB_LOGF(log,
              "StructuredDataDarwinLog::%s() "
              "ConfigureStructuredData() call failed "
              "(process uid %u): %s",
              __FUNCTION__, process_sp->GetUniqueID(), error.AsCString());
    Debugger::ReportError("failed to configure DarwinLog support",
                          debugger_sp->GetID());
    m_is_enabled = false;
  } else {
    m_is_enabled = true;
    LLDB_LOGF(log,
              "StructuredDataDarwinLog::%s() success via direct "
              "configuration (process uid %u)",
              __FUNCTION__, process_sp->GetUniqueID());
  }
}
