diff options
| author | Johnny Chen <johnny.chen@apple.com> | 2010-10-28 17:27:46 +0000 |
|---|---|---|
| committer | Johnny Chen <johnny.chen@apple.com> | 2010-10-28 17:27:46 +0000 |
| commit | b7234e40140cffea4868a0952ef26f102100a3fd (patch) | |
| tree | 1ef37bfb6bef10455dbd52d73e64b0e608dc1064 | |
| parent | 8e0073008a29615b1749af4128c49c07cf77c200 (diff) | |
| download | bcm5719-llvm-b7234e40140cffea4868a0952ef26f102100a3fd.tar.gz bcm5719-llvm-b7234e40140cffea4868a0952ef26f102100a3fd.zip | |
Check in an initial implementation of the "breakpoint clear" command, whose purpose is clear
the breakpoint associated with the (filename, line_number) combo when an arrow is pointing to
a source position using Emacs Grand Unified Debugger library to interact with lldb.
The current implmentation is insufficient in that it only asks the breakpoint whether it is
associated with a breakpoint resolver with FileLine type and whether it matches the (filename, line_number)
combo. There are other breakpoint resolver types whose breakpoint locations can potentially
match the (filename, line_number) combo.
The BreakpointResolver, BreakpointResolverName, BreakpointResolverAddress, and BreakpointResolverFileLine
classes have extra static classof methods to support LLVM style type inquiry through isa, cast, and dyn_cast.
The Breakpoint class has an API method bool GetMatchingFileLine(...) which is invoked from CommandObjectBreak.cpp
to implement the "breakpoint clear" command.
llvm-svn: 117562
| -rw-r--r-- | lldb/include/lldb/Breakpoint/Breakpoint.h | 15 | ||||
| -rw-r--r-- | lldb/include/lldb/Breakpoint/BreakpointResolver.h | 25 | ||||
| -rw-r--r-- | lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h | 6 | ||||
| -rw-r--r-- | lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h | 7 | ||||
| -rw-r--r-- | lldb/include/lldb/Breakpoint/BreakpointResolverName.h | 6 | ||||
| -rw-r--r-- | lldb/source/Breakpoint/Breakpoint.cpp | 25 | ||||
| -rw-r--r-- | lldb/source/Breakpoint/BreakpointResolver.cpp | 5 | ||||
| -rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverAddress.cpp | 2 | ||||
| -rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverFileLine.cpp | 2 | ||||
| -rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverName.cpp | 6 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectBreakpoint.cpp | 197 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectBreakpoint.h | 62 |
12 files changed, 345 insertions, 13 deletions
diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h index 91b059a5be7..4349aaaa5f7 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -458,6 +458,21 @@ public: void GetResolverDescription (Stream *s); + //------------------------------------------------------------------ + /// Find breakpoint locations which match the (filename, line_number) description. + /// The breakpoint location collection is to be filled with the matching locations. + /// It should be initialized with 0 size by the API client. + /// + /// @return + /// True if there is a match + /// + /// The locations which match the filename and line_number in loc_coll. If its + /// size is 0 and true is returned, it means the breakpoint fully matches the + /// description. + //------------------------------------------------------------------ + bool GetMatchingFileLine(const ConstString &filename, uint32_t line_number, + BreakpointLocationCollection &loc_coll); + void GetFilterDescription (Stream *s); diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/lldb/include/lldb/Breakpoint/BreakpointResolver.h index 1b1284f7970..bea836472b1 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolver.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolver.h @@ -52,11 +52,13 @@ public: /// /// @param[in] bkpt /// The breakpoint that owns this resolver. + /// @param[in] resolverType + /// The concrete breakpoint resolver type for this breakpoint. /// /// @result /// Returns breakpoint location id. //------------------------------------------------------------------ - BreakpointResolver (Breakpoint *bkpt); + BreakpointResolver (Breakpoint *bkpt, unsigned char resolverType); //------------------------------------------------------------------ /// The Destructor is virtual, all significant breakpoint resolvers derive @@ -110,11 +112,32 @@ public: virtual void Dump (Stream *s) const = 0; + //------------------------------------------------------------------ + /// An enumeration for keeping track of the concrete subclass that + /// is actually instantiated. Values of this enumeration are kept in the + /// BreakpointResolver's SubclassID field. They are used for concrete type + /// identification. + enum ResolverTy { + FileLineResolver, // This is an instance of BreakpointResolverFileLine + AddressResolver, // This is an instance of BreakpointResolverAddress + NameResolver // This is an instance of BreakpointResolverName + }; + + //------------------------------------------------------------------ + /// getResolverID - Return an ID for the concrete type of this object. This + /// is used to implement the LLVM classof checks. This should not be used + /// for any other purpose, as the values may change as LLDB evolves. + unsigned getResolverID() const { + return SubclassID; + } + protected: Target *m_target; // Every resolver has a target. Breakpoint *m_breakpoint; // This is the breakpoint we add locations to. private: + // Subclass identifier (for llvm isa/dyn_cast) + const unsigned char SubclassID; DISALLOW_COPY_AND_ASSIGN(BreakpointResolver); }; diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h b/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h index 6807bc0d8df..4ca4a405957 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverAddress.h @@ -56,6 +56,12 @@ public: virtual void Dump (Stream *s) const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverAddress *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::AddressResolver; + } + protected: Address m_addr; diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h index 285ef525f9f..395bcdbf3ab 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverFileLine.h @@ -51,7 +51,14 @@ public: virtual void Dump (Stream *s) const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverFileLine *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::FileLineResolver; + } + protected: + friend class Breakpoint; FileSpec m_file_spec; // This is the file spec we are looking for. uint32_t m_line_number; // This is the line number that we are looking for. bool m_inlines; // This determines whether the resolver looks for inlined functions or not. diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h index 9d5e68ecc07..3593efead77 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h @@ -61,6 +61,12 @@ public: virtual void Dump (Stream *s) const; + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverName *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::NameResolver; + } + protected: ConstString m_func_name; // "m_basename_filter" is used to filter results after searching for diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp index 7f8b7dfff3c..11782d015f3 100644 --- a/lldb/source/Breakpoint/Breakpoint.cpp +++ b/lldb/source/Breakpoint/Breakpoint.cpp @@ -16,7 +16,9 @@ #include "lldb/Core/Address.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Breakpoint/BreakpointLocationCollection.h" #include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Breakpoint/BreakpointResolverFileLine.h" #include "lldb/Core/Log.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/SearchFilter.h" @@ -26,9 +28,11 @@ #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" #include "lldb/lldb-private-log.h" +#include "llvm/Support/Casting.h" using namespace lldb; using namespace lldb_private; +using namespace llvm; const ConstString & Breakpoint::GetEventIdentifier () @@ -533,6 +537,27 @@ Breakpoint::GetResolverDescription (Stream *s) m_resolver_sp->GetDescription (s); } + +bool +Breakpoint::GetMatchingFileLine (const ConstString &filename, uint32_t line_number, BreakpointLocationCollection &loc_coll) +{ + // TODO: To be correct, this method needs to fill the breakpoint location collection + // with the location IDs which match the filename and line_number. + // + + if (m_resolver_sp) + { + BreakpointResolverFileLine *resolverFileLine = dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get()); + if (resolverFileLine && + resolverFileLine->m_file_spec.GetFilename() == filename && + resolverFileLine->m_line_number == line_number) + { + return true; + } + } + return false; +} + void Breakpoint::GetFilterDescription (Stream *s) { diff --git a/lldb/source/Breakpoint/BreakpointResolver.cpp b/lldb/source/Breakpoint/BreakpointResolver.cpp index e0fbfde7932..b22fa1e6dbc 100644 --- a/lldb/source/Breakpoint/BreakpointResolver.cpp +++ b/lldb/source/Breakpoint/BreakpointResolver.cpp @@ -30,8 +30,9 @@ using namespace lldb_private; //---------------------------------------------------------------------- // BreakpointResolver: //---------------------------------------------------------------------- -BreakpointResolver::BreakpointResolver (Breakpoint *bkpt) : - m_breakpoint (bkpt) +BreakpointResolver::BreakpointResolver (Breakpoint *bkpt, const unsigned char resolverTy) : + m_breakpoint (bkpt), + SubclassID (resolverTy) { } diff --git a/lldb/source/Breakpoint/BreakpointResolverAddress.cpp b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp index 3e462d0c9fb..1949b1b01d0 100644 --- a/lldb/source/Breakpoint/BreakpointResolverAddress.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverAddress.cpp @@ -31,7 +31,7 @@ BreakpointResolverAddress::BreakpointResolverAddress Breakpoint *bkpt, const Address &addr ) : - BreakpointResolver (bkpt), + BreakpointResolver (bkpt, BreakpointResolver::AddressResolver), m_addr (addr) { } diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp index cb620f9a853..187822f8144 100644 --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -31,7 +31,7 @@ BreakpointResolverFileLine::BreakpointResolverFileLine uint32_t line_no, bool check_inlines ) : - BreakpointResolver (bkpt), + BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver), m_file_spec (file_spec), m_line_number (line_no), m_inlines (check_inlines) diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp index ee5c86aa8d8..980a0f5127e 100644 --- a/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -28,7 +28,7 @@ BreakpointResolverName::BreakpointResolverName uint32_t func_name_type_mask, Breakpoint::MatchType type ) : - BreakpointResolver (bkpt), + BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_func_name (), m_basename_filter (), m_func_name_type_mask (func_name_type_mask), @@ -94,7 +94,7 @@ BreakpointResolverName::BreakpointResolverName Breakpoint *bkpt, RegularExpression &func_regex ) : - BreakpointResolver (bkpt), + BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_func_name (NULL), m_class_name (NULL), m_regex (func_regex), @@ -110,7 +110,7 @@ BreakpointResolverName::BreakpointResolverName const char *method, Breakpoint::MatchType type ) : - BreakpointResolver (bkpt), + BreakpointResolver (bkpt, BreakpointResolver::NameResolver), m_func_name (method), m_class_name (class_name), m_regex (), diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index 7894f55c313..237ac89a35e 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -28,6 +28,8 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" +#include <vector> + using namespace lldb; using namespace lldb_private; @@ -526,23 +528,27 @@ CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInter bool status; CommandObjectSP list_command_object (new CommandObjectBreakpointList (interpreter)); - CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter)); CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable (interpreter)); CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable (interpreter)); + CommandObjectSP clear_command_object (new CommandObjectBreakpointClear (interpreter)); + CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter)); CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter)); CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter)); CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter)); - command_command_object->SetCommandName ("breakpoint command"); + list_command_object->SetCommandName ("breakpoint list"); enable_command_object->SetCommandName("breakpoint enable"); disable_command_object->SetCommandName("breakpoint disable"); - list_command_object->SetCommandName ("breakpoint list"); - modify_command_object->SetCommandName ("breakpoint modify"); + clear_command_object->SetCommandName("breakpoint clear"); + delete_command_object->SetCommandName("breakpoint delete"); set_command_object->SetCommandName("breakpoint set"); + command_command_object->SetCommandName ("breakpoint command"); + modify_command_object->SetCommandName ("breakpoint modify"); status = LoadSubCommand ("list", list_command_object); status = LoadSubCommand ("enable", enable_command_object); status = LoadSubCommand ("disable", disable_command_object); + status = LoadSubCommand ("clear", clear_command_object); status = LoadSubCommand ("delete", delete_command_object); status = LoadSubCommand ("set", set_command_object); status = LoadSubCommand ("command", command_command_object); @@ -1039,6 +1045,189 @@ CommandObjectBreakpointDisable::Execute } //------------------------------------------------------------------------- +// CommandObjectBreakpointClear::CommandOptions +//------------------------------------------------------------------------- +#pragma mark Clear::CommandOptions + +CommandObjectBreakpointClear::CommandOptions::CommandOptions() : + Options (), + m_filename (), + m_line_num (0) +{ +} + +CommandObjectBreakpointClear::CommandOptions::~CommandOptions () +{ +} + +lldb::OptionDefinition +CommandObjectBreakpointClear::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, + "Specify the breakpoint by source location in this particular file."}, + + { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, + "Specify the breakpoint by source location at this particular line."}, + + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } +}; + +const lldb::OptionDefinition* +CommandObjectBreakpointClear::CommandOptions::GetDefinitions () +{ + return g_option_table; +} + +Error +CommandObjectBreakpointClear::CommandOptions::SetOptionValue (int option_idx, const char *option_arg) +{ + Error error; + char short_option = (char) m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'f': + m_filename = option_arg; + break; + + case 'l': + m_line_num = Args::StringToUInt32 (option_arg, 0); + break; + + default: + error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); + break; + } + + return error; +} + +void +CommandObjectBreakpointClear::CommandOptions::ResetOptionValues () +{ + Options::ResetOptionValues(); + + m_filename.clear(); + m_line_num = 0; +} + +//------------------------------------------------------------------------- +// CommandObjectBreakpointClear +//------------------------------------------------------------------------- +#pragma mark Clear + +CommandObjectBreakpointClear::CommandObjectBreakpointClear (CommandInterpreter &interpreter) : + CommandObject (interpreter, + "breakpoint clear", + "Clears a breakpoint or set of breakpoints in the executable.", + "breakpoint clear <cmd-options>") +{ +} + +CommandObjectBreakpointClear::~CommandObjectBreakpointClear () +{ +} + +Options * +CommandObjectBreakpointClear::GetOptions () +{ + return &m_options; +} + +bool +CommandObjectBreakpointClear::Execute +( + Args& command, + CommandReturnObject &result +) +{ + Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); + if (target == NULL) + { + result.AppendError ("Invalid target. No existing target or breakpoints."); + result.SetStatus (eReturnStatusFailed); + return false; + } + + // The following are the various types of breakpoints that could be cleared: + // 1). -f -l (clearing breakpoint by source location) + + BreakpointClearType break_type = eClearTypeInvalid; + + if (m_options.m_line_num != 0) + break_type = eClearTypeFileAndLine; + + Mutex::Locker locker; + target->GetBreakpointList().GetListMutex(locker); + + BreakpointList &breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); + + // Early return if there's no breakpoint at all. + if (num_breakpoints == 0) + { + result.AppendError ("Breakpoint clear: No breakpoint cleared."); + result.SetStatus (eReturnStatusFailed); + return result.Succeeded(); + } + + // Find matching breakpoints and delete them. + + // First create a copy of all the IDs. + std::vector<break_id_t> BreakIDs; + for (size_t i = 0; i < num_breakpoints; ++i) + BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i).get()->GetID()); + + int num_cleared = 0; + StreamString ss; + switch (break_type) + { + case eClearTypeFileAndLine: // Breakpoint by source position + { + const ConstString filename(m_options.m_filename.c_str()); + BreakpointLocationCollection loc_coll; + + for (size_t i = 0; i < num_breakpoints; ++i) + { + Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); + + if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) + { + // If the collection size is 0, it's a full match and we can just remove the breakpoint. + if (loc_coll.GetSize() == 0) + { + bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); + ss.EOL(); + target->RemoveBreakpointByID (bp->GetID()); + ++num_cleared; + } + } + } + } + break; + + default: + break; + } + + if (num_cleared > 0) + { + StreamString &output_stream = result.GetOutputStream(); + output_stream.Printf ("%d breakpoints cleared:\n", num_cleared); + output_stream << ss.GetData(); + output_stream.EOL(); + result.SetStatus (eReturnStatusSuccessFinishNoResult); + } + else + { + result.AppendError ("Breakpoint clear: No breakpoint cleared."); + result.SetStatus (eReturnStatusFailed); + } + + return result.Succeeded(); +} + +//------------------------------------------------------------------------- // CommandObjectBreakpointDelete //------------------------------------------------------------------------- #pragma mark Delete diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h index 45bdb16a255..fb13576479a 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.h +++ b/lldb/source/Commands/CommandObjectBreakpoint.h @@ -43,7 +43,7 @@ public: }; //------------------------------------------------------------------------- -// CommandObjectMultiwordBreakpointSet +// CommandObjectdBreakpointSet //------------------------------------------------------------------------- @@ -271,6 +271,66 @@ private: }; //------------------------------------------------------------------------- +// CommandObjectBreakpointClear +//------------------------------------------------------------------------- + + +class CommandObjectBreakpointClear : public CommandObject +{ +public: + + typedef enum BreakpointClearType + { + eClearTypeInvalid, + eClearTypeFileAndLine, + } BreakpointClearType; + + CommandObjectBreakpointClear (CommandInterpreter &interpreter); + + virtual + ~CommandObjectBreakpointClear (); + + virtual bool + Execute (Args& command, + CommandReturnObject &result); + + virtual Options * + GetOptions (); + + class CommandOptions : public Options + { + public: + + CommandOptions (); + + virtual + ~CommandOptions (); + + virtual Error + SetOptionValue (int option_idx, const char *option_arg); + + void + ResetOptionValues (); + + const lldb::OptionDefinition* + GetDefinitions (); + + // Options table: Required for subclasses of Options. + + static lldb::OptionDefinition g_option_table[]; + + // Instance variables to hold the values for command options. + + std::string m_filename; + uint32_t m_line_num; + + }; + +private: + CommandOptions m_options; +}; + +//------------------------------------------------------------------------- // CommandObjectBreakpointDelete //------------------------------------------------------------------------- |

