This allows us to collect useful metrics about lldb debugging sessions. I thought that an example would be better than a thousand words: Process 19705 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = step in frame #0: 0x0000000100000fb4 blah`main at blah.c:3 1 int main(void) { 2 int a = 6; -> 3 return 0; 4 } (lldb) statistics enable (lldb) frame var a (int) a = 6 (lldb) expr a (int) $1 = 6 (lldb) statistics disable (lldb) statistics dump Number of expr evaluation successes : 1 Number of expr evaluation failures : 0 Number of frame var successes : 1 Number of frame var failures : 0 Future improvements might include: 1. Passing a file, or implementing categories. The way this patch has been implemented is generic enough to allow this to be extended easily without breaking the grammar. 2. Adding an SBAPI and Python API for use in scripts. Thanks to Jim Ingham for discussing the design with me. <rdar://problem/36555975> Differential Revision: https://reviews.llvm.org/D45547 llvm-svn: 330043
125 lines
4.1 KiB
C++
125 lines
4.1 KiB
C++
//===-- CommandObjectStats.cpp ----------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CommandObjectStats.h"
|
|
#include "lldb/Host/Host.h"
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
|
#include "lldb/Interpreter/CommandReturnObject.h"
|
|
#include "lldb/Target/Target.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
class CommandObjectStatsEnable : public CommandObjectParsed {
|
|
public:
|
|
CommandObjectStatsEnable(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(interpreter, "enable",
|
|
"Enable statistics collection", nullptr,
|
|
eCommandProcessMustBePaused) {}
|
|
|
|
~CommandObjectStatsEnable() override = default;
|
|
|
|
protected:
|
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
|
Target *target = GetSelectedOrDummyTarget();
|
|
|
|
if (target->GetCollectingStats()) {
|
|
result.AppendError("statistics already enabled");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
target->SetCollectingStats(true);
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class CommandObjectStatsDisable : public CommandObjectParsed {
|
|
public:
|
|
CommandObjectStatsDisable(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(interpreter, "disable",
|
|
"Disable statistics collection", nullptr,
|
|
eCommandProcessMustBePaused) {}
|
|
|
|
~CommandObjectStatsDisable() override = default;
|
|
|
|
protected:
|
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
|
Target *target = GetSelectedOrDummyTarget();
|
|
|
|
if (!target->GetCollectingStats()) {
|
|
result.AppendError("need to enable statistics before disabling them");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
target->SetCollectingStats(false);
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class CommandObjectStatsDump : public CommandObjectParsed {
|
|
private:
|
|
std::string GetStatDescription(lldb_private::StatisticKind K) {
|
|
switch (K) {
|
|
case StatisticKind::ExpressionSuccessful:
|
|
return "Number of expr evaluation successes";
|
|
case StatisticKind::ExpressionFailure:
|
|
return "Number of expr evaluation failures";
|
|
case StatisticKind::FrameVarSuccess:
|
|
return "Number of frame var successes";
|
|
case StatisticKind::FrameVarFailure:
|
|
return "Number of frame var failures";
|
|
case StatisticKind::StatisticMax:
|
|
return "";
|
|
}
|
|
llvm_unreachable("Statistic not registered!");
|
|
}
|
|
|
|
public:
|
|
CommandObjectStatsDump(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(interpreter, "dump", "Dump statistics results",
|
|
nullptr, eCommandProcessMustBePaused) {}
|
|
|
|
~CommandObjectStatsDump() override = default;
|
|
|
|
protected:
|
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
|
Target *target = GetSelectedOrDummyTarget();
|
|
|
|
uint32_t i = 0;
|
|
for (auto &stat : target->GetStatistics()) {
|
|
result.AppendMessageWithFormat(
|
|
"%s : %u\n",
|
|
GetStatDescription(static_cast<lldb_private::StatisticKind>(i))
|
|
.c_str(),
|
|
stat);
|
|
i += 1;
|
|
}
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
CommandObjectStats::CommandObjectStats(CommandInterpreter &interpreter)
|
|
: CommandObjectMultiword(interpreter, "statistics",
|
|
"Print statistics about a debugging session",
|
|
"statistics <subcommand> [<subcommand-options>]") {
|
|
LoadSubCommand("enable",
|
|
CommandObjectSP(new CommandObjectStatsEnable(interpreter)));
|
|
LoadSubCommand("disable",
|
|
CommandObjectSP(new CommandObjectStatsDisable(interpreter)));
|
|
LoadSubCommand("dump",
|
|
CommandObjectSP(new CommandObjectStatsDump(interpreter)));
|
|
}
|
|
|
|
CommandObjectStats::~CommandObjectStats() = default;
|