Add initial implementation of watchpoint commands for list, enable, disable, and delete.
Test cases to be added later. llvm-svn: 140322
This commit is contained in:
parent
0542df5198
commit
f04ee930a0
|
@ -85,7 +85,7 @@ public:
|
|||
return m_hw_preferred;
|
||||
}
|
||||
|
||||
bool
|
||||
virtual bool
|
||||
IsHardware () const
|
||||
{
|
||||
return m_hw_index != LLDB_INVALID_INDEX32;
|
||||
|
|
|
@ -40,6 +40,9 @@ public:
|
|||
void
|
||||
SetEnabled (bool enabled);
|
||||
|
||||
virtual bool
|
||||
IsHardware () const;
|
||||
|
||||
virtual bool
|
||||
ShouldStop (StoppointCallbackContext *context);
|
||||
|
||||
|
@ -55,7 +58,8 @@ public:
|
|||
void DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const;
|
||||
|
||||
private:
|
||||
bool m_enabled; // Is this breakpoint enabled
|
||||
bool m_enabled; // Is this watchpoint enabled
|
||||
bool m_is_hardware; // Is this a hardware watchpoint
|
||||
uint32_t m_watch_read:1, // 1 if we stop when the watched data is read from
|
||||
m_watch_write:1, // 1 if we stop when the watched data is written to
|
||||
m_watch_was_read:1, // Set to 1 when watchpoint is hit for a read access
|
||||
|
|
|
@ -224,7 +224,6 @@ public:
|
|||
GetListMutex (lldb_private::Mutex::Locker &locker);
|
||||
|
||||
protected:
|
||||
typedef std::vector<lldb::WatchpointLocationSP> collection;
|
||||
typedef std::map<lldb::addr_t, lldb::WatchpointLocationSP> addr_map;
|
||||
|
||||
addr_map::iterator
|
||||
|
@ -233,7 +232,6 @@ protected:
|
|||
addr_map::const_iterator
|
||||
GetIDConstIterator(lldb::watch_id_t watchID) const;
|
||||
|
||||
collection m_locations;
|
||||
addr_map m_address_to_location;
|
||||
mutable Mutex m_mutex;
|
||||
};
|
||||
|
|
|
@ -442,6 +442,7 @@
|
|||
9AC70390117675270086C050 /* SBInstructionList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038F117675270086C050 /* SBInstructionList.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; };
|
||||
9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; };
|
||||
B207C4931429607D00F36E4E /* CommandObjectWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B207C4921429607D00F36E4E /* CommandObjectWatchpoint.cpp */; };
|
||||
B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2462246141AD37D00F3D409 /* OptionGroupWatchpoint.cpp */; };
|
||||
B271B11413D6139300C3FEDB /* FormatClasses.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94A9112D13D5DF210046D8A6 /* FormatClasses.cpp */; };
|
||||
B27318421416AC12006039C8 /* WatchpointLocationList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B27318411416AC12006039C8 /* WatchpointLocationList.cpp */; };
|
||||
|
@ -1304,6 +1305,8 @@
|
|||
AF68D32F1255A110002FF25B /* UnwindLLDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindLLDB.cpp; path = Utility/UnwindLLDB.cpp; sourceTree = "<group>"; };
|
||||
AF68D3301255A110002FF25B /* UnwindLLDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnwindLLDB.h; path = Utility/UnwindLLDB.h; sourceTree = "<group>"; };
|
||||
AF94005711C03F6500085DB9 /* SymbolVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolVendor.cpp; path = source/Symbol/SymbolVendor.cpp; sourceTree = "<group>"; };
|
||||
B207C4921429607D00F36E4E /* CommandObjectWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectWatchpoint.cpp; path = source/Commands/CommandObjectWatchpoint.cpp; sourceTree = "<group>"; };
|
||||
B207C4941429609C00F36E4E /* CommandObjectWatchpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CommandObjectWatchpoint.h; path = source/Commands/CommandObjectWatchpoint.h; sourceTree = "<group>"; };
|
||||
B23DD24F12EDFAC1000C3894 /* ARMUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ARMUtils.h; path = Utility/ARMUtils.h; sourceTree = "<group>"; };
|
||||
B2462246141AD37D00F3D409 /* OptionGroupWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionGroupWatchpoint.cpp; path = source/Interpreter/OptionGroupWatchpoint.cpp; sourceTree = "<group>"; };
|
||||
B2462248141AD39B00F3D409 /* OptionGroupWatchpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OptionGroupWatchpoint.h; path = include/lldb/Interpreter/OptionGroupWatchpoint.h; sourceTree = "<group>"; };
|
||||
|
@ -2257,6 +2260,8 @@
|
|||
9463D4CC13B1798800C230D4 /* CommandObjectType.cpp */,
|
||||
B296983512C2FB2B002D92C3 /* CommandObjectVersion.h */,
|
||||
B296983412C2FB2B002D92C3 /* CommandObjectVersion.cpp */,
|
||||
B207C4941429609C00F36E4E /* CommandObjectWatchpoint.h */,
|
||||
B207C4921429607D00F36E4E /* CommandObjectWatchpoint.cpp */,
|
||||
);
|
||||
name = Commands;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3384,6 +3389,7 @@
|
|||
B2462247141AD37D00F3D409 /* OptionGroupWatchpoint.cpp in Sources */,
|
||||
49A71FE7141FFA5C00D59478 /* IRInterpreter.cpp in Sources */,
|
||||
49A71FE8141FFACF00D59478 /* DataEncoder.cpp in Sources */,
|
||||
B207C4931429607D00F36E4E /* CommandObjectWatchpoint.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@ using namespace lldb_private;
|
|||
WatchpointLocation::WatchpointLocation (lldb::addr_t addr, size_t size, bool hardware) :
|
||||
StoppointLocation (GetNextID(), addr, size, hardware),
|
||||
m_enabled(0),
|
||||
m_is_hardware(hardware),
|
||||
m_watch_read(0),
|
||||
m_watch_write(0),
|
||||
m_watch_was_read(0),
|
||||
|
@ -58,28 +59,36 @@ WatchpointLocation::SetDeclInfo (std::string &str)
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
WatchpointLocation::IsHardware () const
|
||||
{
|
||||
return m_is_hardware;
|
||||
}
|
||||
|
||||
// RETURNS - true if we should stop at this breakpoint, false if we
|
||||
// should continue.
|
||||
|
||||
bool
|
||||
WatchpointLocation::ShouldStop (StoppointCallbackContext *context)
|
||||
{
|
||||
m_hit_count++;
|
||||
++m_hit_count;
|
||||
|
||||
if (m_hit_count > m_ignore_count)
|
||||
{
|
||||
uint32_t access = 0;
|
||||
if (m_watch_was_read)
|
||||
access |= LLDB_WATCH_TYPE_READ;
|
||||
if (m_watch_was_written)
|
||||
access |= LLDB_WATCH_TYPE_WRITE;
|
||||
if (!IsEnabled())
|
||||
return false;
|
||||
|
||||
if (m_callback)
|
||||
return m_callback(m_callback_baton, context, GetID(), access);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (m_hit_count <= GetIgnoreCount())
|
||||
return false;
|
||||
|
||||
uint32_t access = 0;
|
||||
if (m_watch_was_read)
|
||||
access |= LLDB_WATCH_TYPE_READ;
|
||||
if (m_watch_was_written)
|
||||
access |= LLDB_WATCH_TYPE_WRITE;
|
||||
|
||||
if (m_callback)
|
||||
return m_callback(m_callback_baton, context, GetID(), access);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -20,7 +20,6 @@ using namespace lldb;
|
|||
using namespace lldb_private;
|
||||
|
||||
WatchpointLocationList::WatchpointLocationList() :
|
||||
m_locations (),
|
||||
m_address_to_location (),
|
||||
m_mutex (Mutex::eMutexTypeRecursive)
|
||||
{
|
||||
|
@ -41,21 +40,10 @@ WatchpointLocationList::Add (const WatchpointLocationSP &wp_loc_sp)
|
|||
addr_map::iterator iter = m_address_to_location.find(wp_addr);
|
||||
|
||||
if (iter == m_address_to_location.end())
|
||||
{
|
||||
m_address_to_location.insert(iter, addr_map::value_type(wp_addr, wp_loc_sp));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_address_to_location[wp_addr] = wp_loc_sp;
|
||||
collection::iterator pos, end = m_locations.end();
|
||||
for (pos = m_locations.begin(); pos != end; ++pos)
|
||||
if ((*pos)->GetLoadAddress() == wp_addr)
|
||||
{
|
||||
m_locations.erase(pos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_locations.push_back(wp_loc_sp);
|
||||
|
||||
return wp_loc_sp->GetID();
|
||||
}
|
||||
|
||||
|
@ -154,9 +142,12 @@ WatchpointLocationList::GetByIndex (uint32_t i)
|
|||
{
|
||||
Mutex::Locker locker (m_mutex);
|
||||
WatchpointLocationSP wp_loc_sp;
|
||||
if (i < m_locations.size())
|
||||
wp_loc_sp = m_locations[i];
|
||||
|
||||
if (i < m_address_to_location.size())
|
||||
{
|
||||
addr_map::const_iterator pos = m_address_to_location.begin();
|
||||
std::advance(pos, i);
|
||||
wp_loc_sp = pos->second;
|
||||
}
|
||||
return wp_loc_sp;
|
||||
}
|
||||
|
||||
|
@ -165,9 +156,12 @@ WatchpointLocationList::GetByIndex (uint32_t i) const
|
|||
{
|
||||
Mutex::Locker locker (m_mutex);
|
||||
WatchpointLocationSP wp_loc_sp;
|
||||
if (i < m_locations.size())
|
||||
wp_loc_sp = m_locations[i];
|
||||
|
||||
if (i < m_address_to_location.size())
|
||||
{
|
||||
addr_map::const_iterator pos = m_address_to_location.begin();
|
||||
std::advance(pos, i);
|
||||
wp_loc_sp = pos->second;
|
||||
}
|
||||
return wp_loc_sp;
|
||||
}
|
||||
|
||||
|
@ -175,17 +169,10 @@ bool
|
|||
WatchpointLocationList::Remove (lldb::watch_id_t watch_id)
|
||||
{
|
||||
Mutex::Locker locker (m_mutex);
|
||||
addr_map::iterator pos = GetIDIterator(watch_id); // Predicate
|
||||
addr_map::iterator pos = GetIDIterator(watch_id);
|
||||
if (pos != m_address_to_location.end())
|
||||
{
|
||||
m_address_to_location.erase(pos);
|
||||
collection::iterator pos, end = m_locations.end();
|
||||
for (pos = m_locations.begin(); pos != end; ++pos)
|
||||
if ((*pos)->GetID() == watch_id)
|
||||
{
|
||||
m_locations.erase(pos);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -205,6 +192,7 @@ WatchpointLocationList::GetHitCount () const
|
|||
bool
|
||||
WatchpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::watch_id_t watch_id)
|
||||
{
|
||||
|
||||
WatchpointLocationSP wp_loc_sp = FindByID (watch_id);
|
||||
if (wp_loc_sp)
|
||||
{
|
||||
|
@ -245,14 +233,7 @@ void
|
|||
WatchpointLocationList::RemoveAll ()
|
||||
{
|
||||
Mutex::Locker locker(m_mutex);
|
||||
|
||||
addr_map::iterator pos, end = m_address_to_location.end();
|
||||
for (pos = m_address_to_location.begin(); pos != end; ++pos)
|
||||
m_address_to_location.erase(pos);
|
||||
|
||||
collection::iterator p, e = m_locations.end();
|
||||
for (p = m_locations.begin(); p != e; ++pos)
|
||||
m_locations.erase(p);
|
||||
m_address_to_location.clear();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -0,0 +1,557 @@
|
|||
//===-- CommandObjectWatchpoint.cpp -----------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CommandObjectWatchpoint.h"
|
||||
|
||||
// C Includes
|
||||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Breakpoint/WatchpointLocation.h"
|
||||
#include "lldb/Breakpoint/WatchpointLocationList.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Interpreter/CommandInterpreter.h"
|
||||
#include "lldb/Interpreter/CommandReturnObject.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Interpreter/CommandCompletions.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
static void
|
||||
AddWatchpointDescription(Stream *s, WatchpointLocation *wp_loc, lldb::DescriptionLevel level)
|
||||
{
|
||||
s->IndentMore();
|
||||
wp_loc->GetDescription(s, level);
|
||||
s->IndentLess();
|
||||
s->EOL();
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result)
|
||||
{
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError ("Invalid target. No existing target or watchpoints.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
bool process_is_valid = target->GetProcessSP() && target->GetProcessSP()->IsAlive();
|
||||
if (!process_is_valid)
|
||||
{
|
||||
result.AppendError ("Thre's no process or it is not alive.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
// Target passes our checks, return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
|
||||
static const char* RSA[4] = { "-", "to", "To", "TO" };
|
||||
|
||||
// Return the index to RSA if found; otherwise -1 is returned.
|
||||
static int32_t
|
||||
WithRSAIndex(llvm::StringRef &Arg)
|
||||
{
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (Arg.find(RSA[i]) != llvm::StringRef::npos)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Return true if wp_ids is successfully populated with the watch ids.
|
||||
// False otherwise.
|
||||
static bool
|
||||
VerifyWatchpointIDs(Args &args, std::vector<uint32_t> &wp_ids)
|
||||
{
|
||||
// Pre-condition: args.GetArgumentCount() > 0.
|
||||
assert(args.GetArgumentCount() > 0);
|
||||
|
||||
llvm::StringRef Minus("-");
|
||||
std::vector<llvm::StringRef> StrRefArgs;
|
||||
std::pair<llvm::StringRef, llvm::StringRef> Pair;
|
||||
size_t i;
|
||||
int32_t idx;
|
||||
// Go through the argments and make a canonical form of arg list containing
|
||||
// only numbers with possible "-" in between.
|
||||
for (i = 0; i < args.GetArgumentCount(); ++i) {
|
||||
llvm::StringRef Arg(args.GetArgumentAtIndex(i));
|
||||
if ((idx = WithRSAIndex(Arg)) == -1) {
|
||||
StrRefArgs.push_back(Arg);
|
||||
continue;
|
||||
}
|
||||
// The Arg contains the range specifier, split it, then.
|
||||
Pair = Arg.split(RSA[idx]);
|
||||
if (!Pair.first.empty())
|
||||
StrRefArgs.push_back(Pair.first);
|
||||
StrRefArgs.push_back(Minus);
|
||||
if (!Pair.second.empty())
|
||||
StrRefArgs.push_back(Pair.second);
|
||||
}
|
||||
// Now process the canonical list and fill in the vector of uint32_t's.
|
||||
// If there is any error, return false and the client should ignore wp_ids.
|
||||
uint32_t beg, end, id;
|
||||
size_t size = StrRefArgs.size();
|
||||
bool in_range = false;
|
||||
for (i = 0; i < size; ++i) {
|
||||
llvm::StringRef Arg = StrRefArgs[i];
|
||||
if (in_range) {
|
||||
// Look for the 'end' of the range. Note StringRef::getAsInteger()
|
||||
// returns true to signify error while parsing.
|
||||
if (Arg.getAsInteger(0, end))
|
||||
return false;
|
||||
// Found a range! Now append the elements.
|
||||
for (id = beg; id <= end; ++id)
|
||||
wp_ids.push_back(id);
|
||||
in_range = false;
|
||||
continue;
|
||||
}
|
||||
if (i < (size - 1) && StrRefArgs[i+1] == Minus) {
|
||||
if (Arg.getAsInteger(0, beg))
|
||||
return false;
|
||||
// Turn on the in_range flag, we are looking for end of range next.
|
||||
++i; in_range = true;
|
||||
continue;
|
||||
}
|
||||
// Otherwise, we have a simple ID. Just append it.
|
||||
if (Arg.getAsInteger(0, beg))
|
||||
return false;
|
||||
wp_ids.push_back(beg);
|
||||
}
|
||||
// It is an error if after the loop, we're still in_range.
|
||||
if (in_range)
|
||||
return false;
|
||||
|
||||
return true; // Success!
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectMultiwordWatchpoint
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark MultiwordWatchpoint
|
||||
|
||||
CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) :
|
||||
CommandObjectMultiword (interpreter,
|
||||
"watchpoint",
|
||||
"A set of commands for operating on watchpoints.",
|
||||
"watchpoint <command> [<command-options>]")
|
||||
{
|
||||
bool status;
|
||||
|
||||
CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter));
|
||||
CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter));
|
||||
CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter));
|
||||
CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter));
|
||||
|
||||
list_command_object->SetCommandName ("watchpoint list");
|
||||
enable_command_object->SetCommandName("watchpoint enable");
|
||||
disable_command_object->SetCommandName("watchpoint disable");
|
||||
delete_command_object->SetCommandName("watchpoint delete");
|
||||
|
||||
status = LoadSubCommand ("list", list_command_object);
|
||||
status = LoadSubCommand ("enable", enable_command_object);
|
||||
status = LoadSubCommand ("disable", disable_command_object);
|
||||
status = LoadSubCommand ("delete", delete_command_object);
|
||||
}
|
||||
|
||||
CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointList::Options
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark List::CommandOptions
|
||||
|
||||
CommandObjectWatchpointList::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
|
||||
Options(interpreter),
|
||||
m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions
|
||||
{
|
||||
}
|
||||
|
||||
CommandObjectWatchpointList::CommandOptions::~CommandOptions()
|
||||
{
|
||||
}
|
||||
|
||||
OptionDefinition
|
||||
CommandObjectWatchpointList::CommandOptions::g_option_table[] =
|
||||
{
|
||||
{ LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone,
|
||||
"Give a brief description of the watchpoint (no location info)."},
|
||||
|
||||
{ LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone,
|
||||
"Give a full description of the watchpoint and its locations."},
|
||||
|
||||
{ LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone,
|
||||
"Explain everything we know about the watchpoint (for debugging debugger bugs)." },
|
||||
|
||||
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
|
||||
};
|
||||
|
||||
const OptionDefinition*
|
||||
CommandObjectWatchpointList::CommandOptions::GetDefinitions()
|
||||
{
|
||||
return g_option_table;
|
||||
}
|
||||
|
||||
Error
|
||||
CommandObjectWatchpointList::CommandOptions::SetOptionValue(uint32_t option_idx, const char *option_arg)
|
||||
{
|
||||
Error error;
|
||||
char short_option = (char) m_getopt_table[option_idx].val;
|
||||
|
||||
switch (short_option)
|
||||
{
|
||||
case 'b':
|
||||
m_level = lldb::eDescriptionLevelBrief;
|
||||
break;
|
||||
case 'f':
|
||||
m_level = lldb::eDescriptionLevelFull;
|
||||
break;
|
||||
case 'v':
|
||||
m_level = lldb::eDescriptionLevelVerbose;
|
||||
break;
|
||||
default:
|
||||
error.SetErrorStringWithFormat("Unrecognized option '%c'.\n", short_option);
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void
|
||||
CommandObjectWatchpointList::CommandOptions::OptionParsingStarting()
|
||||
{
|
||||
m_level = lldb::eDescriptionLevelFull;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointList
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark List
|
||||
|
||||
CommandObjectWatchpointList::CommandObjectWatchpointList(CommandInterpreter &interpreter) :
|
||||
CommandObject(interpreter,
|
||||
"watchpoint list",
|
||||
"List all watchpoints at configurable levels of detail.",
|
||||
NULL),
|
||||
m_options(interpreter)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandObject::AddIDsArgumentData(arg);
|
||||
// Add the entry for the first argument for this command to the object's arguments vector.
|
||||
m_arguments.push_back(arg);
|
||||
}
|
||||
|
||||
CommandObjectWatchpointList::~CommandObjectWatchpointList()
|
||||
{
|
||||
}
|
||||
|
||||
Options *
|
||||
CommandObjectWatchpointList::GetOptions()
|
||||
{
|
||||
return &m_options;
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObjectWatchpointList::Execute(Args& args, CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError ("Invalid target. No current target or watchpoints.");
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList();
|
||||
Mutex::Locker locker;
|
||||
target->GetWatchpointLocationList().GetListMutex(locker);
|
||||
|
||||
size_t num_watchpoints = watchpoints.GetSize();
|
||||
|
||||
if (num_watchpoints == 0)
|
||||
{
|
||||
result.AppendMessage("No watchpoints currently set.");
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
Stream &output_stream = result.GetOutputStream();
|
||||
|
||||
if (args.GetArgumentCount() == 0)
|
||||
{
|
||||
// No watchpoint selected; show info about all currently set watchpoints.
|
||||
result.AppendMessage ("Current watchpoints:");
|
||||
for (size_t i = 0; i < num_watchpoints; ++i)
|
||||
{
|
||||
WatchpointLocation *wp_loc = watchpoints.GetByIndex(i).get();
|
||||
AddWatchpointDescription(&output_stream, wp_loc, m_options.m_level);
|
||||
}
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Particular watchpoints selected; enable them.
|
||||
std::vector<uint32_t> wp_ids;
|
||||
if (!VerifyWatchpointIDs(args, wp_ids))
|
||||
{
|
||||
result.AppendError("Invalid watchpoints specification.");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t size = wp_ids.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
WatchpointLocation *wp_loc = watchpoints.FindByID(wp_ids[i]).get();
|
||||
if (wp_loc)
|
||||
AddWatchpointDescription(&output_stream, wp_loc, m_options.m_level);
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointEnable
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark Enable
|
||||
|
||||
CommandObjectWatchpointEnable::CommandObjectWatchpointEnable(CommandInterpreter &interpreter) :
|
||||
CommandObject(interpreter,
|
||||
"enable",
|
||||
"Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.",
|
||||
NULL)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandObject::AddIDsArgumentData(arg);
|
||||
// Add the entry for the first argument for this command to the object's arguments vector.
|
||||
m_arguments.push_back(arg);
|
||||
}
|
||||
|
||||
CommandObjectWatchpointEnable::~CommandObjectWatchpointEnable()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObjectWatchpointEnable::Execute(Args& args, CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
if (!CheckTargetForWatchpointOperations(target, result))
|
||||
return false;
|
||||
|
||||
Mutex::Locker locker;
|
||||
target->GetWatchpointLocationList().GetListMutex(locker);
|
||||
|
||||
const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList();
|
||||
|
||||
size_t num_watchpoints = watchpoints.GetSize();
|
||||
|
||||
if (num_watchpoints == 0)
|
||||
{
|
||||
result.AppendError("No watchpoints exist to be enabled.");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.GetArgumentCount() == 0)
|
||||
{
|
||||
// No watchpoint selected; enable all currently set watchpoints.
|
||||
target->EnableAllWatchpointLocations();
|
||||
result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints);
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Particular watchpoints selected; enable them.
|
||||
std::vector<uint32_t> wp_ids;
|
||||
if (!VerifyWatchpointIDs(args, wp_ids))
|
||||
{
|
||||
result.AppendError("Invalid watchpoints specification.");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
const size_t size = wp_ids.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (target->EnableWatchpointLocationByID(wp_ids[i]))
|
||||
++count;
|
||||
result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointDisable
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark Disable
|
||||
|
||||
CommandObjectWatchpointDisable::CommandObjectWatchpointDisable(CommandInterpreter &interpreter) :
|
||||
CommandObject(interpreter,
|
||||
"watchpoint disable",
|
||||
"Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.",
|
||||
NULL)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandObject::AddIDsArgumentData(arg);
|
||||
// Add the entry for the first argument for this command to the object's arguments vector.
|
||||
m_arguments.push_back(arg);
|
||||
}
|
||||
|
||||
CommandObjectWatchpointDisable::~CommandObjectWatchpointDisable()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObjectWatchpointDisable::Execute(Args& args, CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
if (!CheckTargetForWatchpointOperations(target, result))
|
||||
return false;
|
||||
|
||||
Mutex::Locker locker;
|
||||
target->GetWatchpointLocationList().GetListMutex(locker);
|
||||
|
||||
const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList();
|
||||
size_t num_watchpoints = watchpoints.GetSize();
|
||||
|
||||
if (num_watchpoints == 0)
|
||||
{
|
||||
result.AppendError("No watchpoints exist to be disabled.");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.GetArgumentCount() == 0)
|
||||
{
|
||||
// No watchpoint selected; disable all currently set watchpoints.
|
||||
if (target->DisableAllWatchpointLocations())
|
||||
{
|
||||
result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints);
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError("Disable all watchpoints failed\n");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Particular watchpoints selected; disable them.
|
||||
std::vector<uint32_t> wp_ids;
|
||||
if (!VerifyWatchpointIDs(args, wp_ids))
|
||||
{
|
||||
result.AppendError("Invalid watchpoints specification.");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
const size_t size = wp_ids.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (target->DisableWatchpointLocationByID(wp_ids[i]))
|
||||
++count;
|
||||
result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
|
||||
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointDelete
|
||||
//-------------------------------------------------------------------------
|
||||
#pragma mark Delete
|
||||
|
||||
CommandObjectWatchpointDelete::CommandObjectWatchpointDelete(CommandInterpreter &interpreter) :
|
||||
CommandObject(interpreter,
|
||||
"watchpoint delete",
|
||||
"Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.",
|
||||
NULL)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandObject::AddIDsArgumentData(arg);
|
||||
// Add the entry for the first argument for this command to the object's arguments vector.
|
||||
m_arguments.push_back(arg);
|
||||
}
|
||||
|
||||
CommandObjectWatchpointDelete::~CommandObjectWatchpointDelete()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CommandObjectWatchpointDelete::Execute(Args& args, CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
if (!CheckTargetForWatchpointOperations(target, result))
|
||||
return false;
|
||||
|
||||
Mutex::Locker locker;
|
||||
target->GetWatchpointLocationList().GetListMutex(locker);
|
||||
|
||||
const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList();
|
||||
|
||||
size_t num_watchpoints = watchpoints.GetSize();
|
||||
|
||||
if (num_watchpoints == 0)
|
||||
{
|
||||
result.AppendError("No watchpoints exist to be deleted.");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (args.GetArgumentCount() == 0)
|
||||
{
|
||||
if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true))
|
||||
{
|
||||
result.AppendMessage("Operation cancelled...");
|
||||
}
|
||||
else
|
||||
{
|
||||
target->RemoveAllWatchpointLocations();
|
||||
result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints);
|
||||
}
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Particular watchpoints selected; delete them.
|
||||
std::vector<uint32_t> wp_ids;
|
||||
if (!VerifyWatchpointIDs(args, wp_ids))
|
||||
{
|
||||
result.AppendError("Invalid watchpoints specification.");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
const size_t size = wp_ids.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
if (target->RemoveWatchpointLocationByID(wp_ids[i]))
|
||||
++count;
|
||||
result.AppendMessageWithFormat("%d watchpoints deleted.\n",count);
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
//===-- CommandObjectWatchpoint.h -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_CommandObjectWatchpoint_h_
|
||||
#define liblldb_CommandObjectWatchpoint_h_
|
||||
|
||||
// C Includes
|
||||
// C++ Includes
|
||||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/Interpreter/CommandObjectMultiword.h"
|
||||
#include "lldb/Interpreter/Options.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectMultiwordWatchpoint
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class CommandObjectMultiwordWatchpoint : public CommandObjectMultiword
|
||||
{
|
||||
public:
|
||||
CommandObjectMultiwordWatchpoint (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectMultiwordWatchpoint ();
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointList
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class CommandObjectWatchpointList : public CommandObject
|
||||
{
|
||||
public:
|
||||
CommandObjectWatchpointList (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectWatchpointList ();
|
||||
|
||||
virtual bool
|
||||
Execute (Args& command,
|
||||
CommandReturnObject &result);
|
||||
|
||||
virtual Options *
|
||||
GetOptions ();
|
||||
|
||||
class CommandOptions : public Options
|
||||
{
|
||||
public:
|
||||
|
||||
CommandOptions (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandOptions ();
|
||||
|
||||
virtual Error
|
||||
SetOptionValue (uint32_t option_idx, const char *option_arg);
|
||||
|
||||
void
|
||||
OptionParsingStarting ();
|
||||
|
||||
const OptionDefinition *
|
||||
GetDefinitions ();
|
||||
|
||||
// Options table: Required for subclasses of Options.
|
||||
|
||||
static OptionDefinition g_option_table[];
|
||||
|
||||
// Instance variables to hold the values for command options.
|
||||
|
||||
lldb::DescriptionLevel m_level;
|
||||
};
|
||||
|
||||
private:
|
||||
CommandOptions m_options;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointEnable
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class CommandObjectWatchpointEnable : public CommandObject
|
||||
{
|
||||
public:
|
||||
CommandObjectWatchpointEnable (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectWatchpointEnable ();
|
||||
|
||||
virtual bool
|
||||
Execute (Args& command,
|
||||
CommandReturnObject &result);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointDisable
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class CommandObjectWatchpointDisable : public CommandObject
|
||||
{
|
||||
public:
|
||||
CommandObjectWatchpointDisable (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectWatchpointDisable ();
|
||||
|
||||
virtual bool
|
||||
Execute (Args& command,
|
||||
CommandReturnObject &result);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CommandObjectWatchpointDelete
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
class CommandObjectWatchpointDelete : public CommandObject
|
||||
{
|
||||
public:
|
||||
CommandObjectWatchpointDelete (CommandInterpreter &interpreter);
|
||||
|
||||
virtual
|
||||
~CommandObjectWatchpointDelete ();
|
||||
|
||||
virtual bool
|
||||
Execute (Args& command,
|
||||
CommandReturnObject &result);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_CommandObjectWatchpoint_h_
|
|
@ -37,6 +37,7 @@
|
|||
#include "../Commands/CommandObjectThread.h"
|
||||
#include "../Commands/CommandObjectType.h"
|
||||
#include "../Commands/CommandObjectVersion.h"
|
||||
#include "../Commands/CommandObjectWatchpoint.h"
|
||||
|
||||
#include "lldb/Interpreter/Args.h"
|
||||
#include "lldb/Interpreter/Options.h"
|
||||
|
@ -266,6 +267,7 @@ CommandInterpreter::LoadCommandDictionary ()
|
|||
m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this));
|
||||
m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this));
|
||||
m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this));
|
||||
m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this));
|
||||
|
||||
std::auto_ptr<CommandObjectRegexCommand>
|
||||
break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
|
||||
|
|
|
@ -586,7 +586,6 @@ Target::DisableAllWatchpointLocations ()
|
|||
if (rc.Fail())
|
||||
return false;
|
||||
}
|
||||
m_watchpoint_location_list.SetEnabledAll (false);
|
||||
return true; // Success!
|
||||
}
|
||||
|
||||
|
@ -612,7 +611,6 @@ Target::EnableAllWatchpointLocations ()
|
|||
if (rc.Fail())
|
||||
return false;
|
||||
}
|
||||
m_watchpoint_location_list.SetEnabledAll (true);
|
||||
return true; // Success!
|
||||
}
|
||||
|
||||
|
@ -631,11 +629,10 @@ Target::DisableWatchpointLocationByID (lldb::watch_id_t watch_id)
|
|||
if (wp_loc_sp)
|
||||
{
|
||||
Error rc = m_process_sp->DisableWatchpoint(wp_loc_sp.get());
|
||||
if (rc.Fail())
|
||||
return false;
|
||||
if (rc.Success())
|
||||
return true;
|
||||
|
||||
wp_loc_sp->SetEnabled (false);
|
||||
return true;
|
||||
// Else, fallthrough.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -655,11 +652,10 @@ Target::EnableWatchpointLocationByID (lldb::watch_id_t watch_id)
|
|||
if (wp_loc_sp)
|
||||
{
|
||||
Error rc = m_process_sp->EnableWatchpoint(wp_loc_sp.get());
|
||||
if (rc.Fail())
|
||||
return false;
|
||||
if (rc.Success())
|
||||
return true;
|
||||
|
||||
wp_loc_sp->SetEnabled (true);
|
||||
return true;
|
||||
// Else, fallthrough.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -62,6 +62,11 @@ class HelloWatchpointTestCase(TestBase):
|
|||
substrs = ['Watchpoint created', 'size = 4', 'type = w',
|
||||
'%s:%d' % (self.source, self.decl)])
|
||||
|
||||
# Use the '-v' option to do verbose listing of the watchpoint.
|
||||
# The hit count should be 0 initially.
|
||||
self.expect("watchpoint list -v",
|
||||
substrs = ['hit_count = 0'])
|
||||
|
||||
self.runCmd("process continue")
|
||||
|
||||
# We should be stopped again due to the watchpoint (write type), but
|
||||
|
@ -76,6 +81,11 @@ class HelloWatchpointTestCase(TestBase):
|
|||
self.expect("process status",
|
||||
substrs = ['exited'])
|
||||
|
||||
# Use the '-v' option to do verbose listing of the watchpoint.
|
||||
# The hit count should now be 1.
|
||||
self.expect("watchpoint list -v",
|
||||
substrs = ['hit_count = 1'])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import atexit
|
||||
|
|
Loading…
Reference in New Issue