diff options
Diffstat (limited to 'lldb/source/Breakpoint/BreakpointIDList.cpp')
-rw-r--r-- | lldb/source/Breakpoint/BreakpointIDList.cpp | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/lldb/source/Breakpoint/BreakpointIDList.cpp b/lldb/source/Breakpoint/BreakpointIDList.cpp new file mode 100644 index 00000000000..895f1b1e3f4 --- /dev/null +++ b/lldb/source/Breakpoint/BreakpointIDList.cpp @@ -0,0 +1,348 @@ +//===-- BreakpointIDList.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Breakpoint/BreakpointIDList.h" + +#include "lldb/Breakpoint/Breakpoint.h" +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Core/Args.h" +#include "lldb/Target/Target.h" + +using namespace lldb; +using namespace lldb_private; + +//---------------------------------------------------------------------- +// class BreakpointIDList +//---------------------------------------------------------------------- + +BreakpointIDList::BreakpointIDList () : +m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID) +{ +} + +BreakpointIDList::~BreakpointIDList () +{ +} + +int +BreakpointIDList::Size() +{ + return m_breakpoint_ids.size(); +} + +BreakpointID & +BreakpointIDList::GetBreakpointIDAtIndex (int index) +{ + if (index < m_breakpoint_ids.size()) + return m_breakpoint_ids[index]; + else + return m_invalid_id; +} + +bool +BreakpointIDList::RemoveBreakpointIDAtIndex (int index) +{ + bool success = false; + if (index < m_breakpoint_ids.size()) + { + BreakpointIDArray::iterator pos; + int i; + + for (pos = m_breakpoint_ids.begin(), i = 0; i != index && pos != m_breakpoint_ids.end(); ++pos, ++i); + assert (i == index); + if (pos != m_breakpoint_ids.end()) + { + m_breakpoint_ids.erase (pos); + success = true; + } + } + return success; +} + +void +BreakpointIDList::Clear() +{ + m_breakpoint_ids.clear (); +} + +bool +BreakpointIDList::AddBreakpointID (BreakpointID bp_id) +{ + m_breakpoint_ids.push_back (bp_id); + + return true; // We don't do any verification in this function, so always return true. +} + +bool +BreakpointIDList::AddBreakpointID (const char *bp_id_str) +{ + BreakpointID temp_bp_id; + break_id_t bp_id; + break_id_t loc_id; + + bool success = BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id); + + if (success) + { + temp_bp_id.SetID (bp_id, loc_id); + m_breakpoint_ids.push_back (temp_bp_id); + } + + return success; +} + +bool +BreakpointIDList::FindBreakpointID (BreakpointID &bp_id, int *position) +{ + bool success = false; + BreakpointIDArray::iterator tmp_pos; + + for (int i = 0; i < m_breakpoint_ids.size(); ++i) + { + BreakpointID tmp_id = m_breakpoint_ids[i]; + if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID() + && tmp_id.GetLocationID() == bp_id.GetLocationID()) + { + success = true; + *position = i; + return true; + } + } + + return false; +} + +bool +BreakpointIDList::FindBreakpointID (const char *bp_id_str, int *position) +{ + BreakpointID temp_bp_id; + break_id_t bp_id; + break_id_t loc_id; + + if (BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id)) + { + temp_bp_id.SetID (bp_id, loc_id); + return FindBreakpointID (temp_bp_id, position); + } + else + return false; +} + +void +BreakpointIDList::InsertStringArray (const char **string_array, int array_size, CommandReturnObject &result) +{ + if (string_array == NULL) + return; + + for (int i = 0; i < array_size; ++i) + { + break_id_t bp_id; + break_id_t loc_id; + + if (BreakpointID::ParseCanonicalReference (string_array[i], &bp_id, &loc_id)) + { + if (bp_id != LLDB_INVALID_BREAK_ID) + { + BreakpointID temp_bp_id(bp_id, loc_id); + m_breakpoint_ids.push_back (temp_bp_id); + } + else + { + result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", string_array[i]); + result.SetStatus (eReturnStatusFailed); + return; + } + } + } + result.SetStatus (eReturnStatusSuccessFinishNoResult); +} + + +// This function takes OLD_ARGS, which is usually the result of breaking the command string arguments into +// an array of space-separated strings, and searches through the arguments for any breakpoint ID range specifiers. +// Any string in the array that is not part of an ID range specifier is copied directly into NEW_ARGS. If any +// ID range specifiers are found, the range is interpreted and a list of canonical breakpoint IDs corresponding to +// all the current breakpoints and locations in the range are added to NEW_ARGS. When this function is done, +// NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range. + +void +BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, + Args &new_args) +{ + char *range_start; + const char *range_end; + const char *current_arg; + int num_old_args = old_args.GetArgumentCount(); + + for (int i = 0; i < num_old_args; ++i) + { + bool is_range = false; + current_arg = old_args.GetArgumentAtIndex (i); + + int range_start_len = 0; + int range_end_pos = 0; + if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos)) + { + is_range = true; + range_start = (char *) malloc (range_start_len + 1); + strncpy (range_start, current_arg, range_start_len); + range_start[range_start_len] = '\0'; + range_end = current_arg + range_end_pos; + } + else if ((i + 2 < num_old_args) + && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1)) + && BreakpointID::IsValidIDExpression (current_arg) + && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2))) + { + range_start = (char *) current_arg; + range_end = old_args.GetArgumentAtIndex (i+2); + is_range = true; + i = i+2; + } + + if (is_range) + { + break_id_t start_bp_id; + break_id_t end_bp_id; + break_id_t start_loc_id; + break_id_t end_loc_id; + + BreakpointID::ParseCanonicalReference (range_start, &start_bp_id, &start_loc_id); + BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id); + + if ((start_bp_id == LLDB_INVALID_BREAK_ID) + || (! target->GetBreakpointByID (start_bp_id))) + { + new_args.Clear(); + result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start); + result.SetStatus (eReturnStatusFailed); + return; + } + + if ((end_bp_id == LLDB_INVALID_BREAK_ID) + || (! target->GetBreakpointByID (end_bp_id))) + { + new_args.Clear(); + result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end); + result.SetStatus (eReturnStatusFailed); + return; + } + + // We have valid range starting & ending breakpoint IDs. Go through all the breakpoints in the + // target and find all the breakpoints that fit into this range, and add them to new_args. + + const BreakpointList& breakpoints = target->GetBreakpointList(); + size_t num_breakpoints = breakpoints.GetSize(); + for (int j = 0; j < num_breakpoints; ++j) + { + Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (j).get(); + break_id_t cur_bp_id = breakpoint->GetID(); + + if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id)) + continue; + + size_t num_locations = breakpoint->GetNumLocations(); + + if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID)) + { + for (int k = 0; k < num_locations; ++k) + { + BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); + if (bp_loc->GetID() >= start_loc_id) + { + StreamString canonical_id_str; + BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); + new_args.AppendArgument (canonical_id_str.GetData()); + } + } + } + else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID)) + { + for (int k = 0; k < num_locations; ++k) + { + BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); + if (bp_loc->GetID() <= end_loc_id) + { + StreamString canonical_id_str; + BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); + new_args.AppendArgument (canonical_id_str.GetData()); + } + } + } + else + { + StreamString canonical_id_str; + BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID); + new_args.AppendArgument (canonical_id_str.GetData()); + } + } + } + else // else is_range was false + { + new_args.AppendArgument (current_arg); + } + } + + result.SetStatus (eReturnStatusSuccessFinishNoResult); + return; +} + +//bool +//BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, const char **range_start, +// const **range_end) +bool +BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, int *range_start_len, int *range_end_pos) +{ + bool is_range_expression = false; + std::string arg_str = in_string; + std::string::size_type idx; + std::string::size_type start_pos = 0; + + //*range_start = NULL; + //*range_end = NULL; + *range_start_len = 0; + *range_end_pos = 0; + + int specifiers_size = 0; + for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i) + ++specifiers_size; + + for (int i = 0; i < specifiers_size && !is_range_expression; ++i) + { + const char *specifier_str = BreakpointID::g_range_specifiers[i]; + int len = strlen (specifier_str); + idx = arg_str.find (BreakpointID::g_range_specifiers[i]); + if (idx != std::string::npos) + { + *range_start_len = idx - start_pos; + std::string start_str = arg_str.substr (start_pos, *range_start_len); + if (idx + len < arg_str.length()) + { + *range_end_pos = idx + len; + std::string end_str = arg_str.substr (*range_end_pos); + if (BreakpointID::IsValidIDExpression (start_str.c_str()) + && BreakpointID::IsValidIDExpression (end_str.c_str())) + { + is_range_expression = true; + //*range_start = start_str; + //*range_end = end_str; + } + } + } + } + + if (!is_range_expression) + { + *range_start_len = 0; + *range_end_pos = 0; + } + + return is_range_expression; +} |