1254721Semaste//===-- BreakpointIDList.cpp ------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Breakpoint/BreakpointIDList.h" 11254721Semaste 12254721Semaste#include "lldb/Breakpoint/Breakpoint.h" 13254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h" 14254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 15254721Semaste#include "lldb/Interpreter/Args.h" 16254721Semaste#include "lldb/Target/Target.h" 17254721Semaste 18254721Semasteusing namespace lldb; 19254721Semasteusing namespace lldb_private; 20254721Semaste 21254721Semaste//---------------------------------------------------------------------- 22254721Semaste// class BreakpointIDList 23254721Semaste//---------------------------------------------------------------------- 24254721Semaste 25254721SemasteBreakpointIDList::BreakpointIDList () : 26254721Semastem_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID) 27254721Semaste{ 28254721Semaste} 29254721Semaste 30254721SemasteBreakpointIDList::~BreakpointIDList () 31254721Semaste{ 32254721Semaste} 33254721Semaste 34254721Semastesize_t 35254721SemasteBreakpointIDList::GetSize() 36254721Semaste{ 37254721Semaste return m_breakpoint_ids.size(); 38254721Semaste} 39254721Semaste 40254721SemasteBreakpointID & 41254721SemasteBreakpointIDList::GetBreakpointIDAtIndex (size_t index) 42254721Semaste{ 43254721Semaste if (index < m_breakpoint_ids.size()) 44254721Semaste return m_breakpoint_ids[index]; 45254721Semaste else 46254721Semaste return m_invalid_id; 47254721Semaste} 48254721Semaste 49254721Semastebool 50254721SemasteBreakpointIDList::RemoveBreakpointIDAtIndex (size_t index) 51254721Semaste{ 52254721Semaste if (index >= m_breakpoint_ids.size()) 53254721Semaste return false; 54254721Semaste 55254721Semaste m_breakpoint_ids.erase (m_breakpoint_ids.begin() + index); 56254721Semaste return true; 57254721Semaste} 58254721Semaste 59254721Semastevoid 60254721SemasteBreakpointIDList::Clear() 61254721Semaste{ 62254721Semaste m_breakpoint_ids.clear (); 63254721Semaste} 64254721Semaste 65254721Semastebool 66254721SemasteBreakpointIDList::AddBreakpointID (BreakpointID bp_id) 67254721Semaste{ 68254721Semaste m_breakpoint_ids.push_back (bp_id); 69254721Semaste 70254721Semaste return true; // We don't do any verification in this function, so always return true. 71254721Semaste} 72254721Semaste 73254721Semastebool 74254721SemasteBreakpointIDList::AddBreakpointID (const char *bp_id_str) 75254721Semaste{ 76254721Semaste BreakpointID temp_bp_id; 77254721Semaste break_id_t bp_id; 78254721Semaste break_id_t loc_id; 79254721Semaste 80254721Semaste bool success = BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id); 81254721Semaste 82254721Semaste if (success) 83254721Semaste { 84254721Semaste temp_bp_id.SetID (bp_id, loc_id); 85254721Semaste m_breakpoint_ids.push_back (temp_bp_id); 86254721Semaste } 87254721Semaste 88254721Semaste return success; 89254721Semaste} 90254721Semaste 91254721Semastebool 92254721SemasteBreakpointIDList::FindBreakpointID (BreakpointID &bp_id, size_t *position) 93254721Semaste{ 94254721Semaste for (size_t i = 0; i < m_breakpoint_ids.size(); ++i) 95254721Semaste { 96254721Semaste BreakpointID tmp_id = m_breakpoint_ids[i]; 97254721Semaste if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID() 98254721Semaste && tmp_id.GetLocationID() == bp_id.GetLocationID()) 99254721Semaste { 100254721Semaste *position = i; 101254721Semaste return true; 102254721Semaste } 103254721Semaste } 104254721Semaste 105254721Semaste return false; 106254721Semaste} 107254721Semaste 108254721Semastebool 109254721SemasteBreakpointIDList::FindBreakpointID (const char *bp_id_str, size_t *position) 110254721Semaste{ 111254721Semaste BreakpointID temp_bp_id; 112254721Semaste break_id_t bp_id; 113254721Semaste break_id_t loc_id; 114254721Semaste 115254721Semaste if (BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id)) 116254721Semaste { 117254721Semaste temp_bp_id.SetID (bp_id, loc_id); 118254721Semaste return FindBreakpointID (temp_bp_id, position); 119254721Semaste } 120254721Semaste else 121254721Semaste return false; 122254721Semaste} 123254721Semaste 124254721Semastevoid 125254721SemasteBreakpointIDList::InsertStringArray (const char **string_array, size_t array_size, CommandReturnObject &result) 126254721Semaste{ 127254721Semaste if (string_array == NULL) 128254721Semaste return; 129254721Semaste 130254721Semaste for (uint32_t i = 0; i < array_size; ++i) 131254721Semaste { 132254721Semaste break_id_t bp_id; 133254721Semaste break_id_t loc_id; 134254721Semaste 135254721Semaste if (BreakpointID::ParseCanonicalReference (string_array[i], &bp_id, &loc_id)) 136254721Semaste { 137254721Semaste if (bp_id != LLDB_INVALID_BREAK_ID) 138254721Semaste { 139254721Semaste BreakpointID temp_bp_id(bp_id, loc_id); 140254721Semaste m_breakpoint_ids.push_back (temp_bp_id); 141254721Semaste } 142254721Semaste else 143254721Semaste { 144254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", string_array[i]); 145254721Semaste result.SetStatus (eReturnStatusFailed); 146254721Semaste return; 147254721Semaste } 148254721Semaste } 149254721Semaste } 150254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 151254721Semaste} 152254721Semaste 153254721Semaste 154254721Semaste// This function takes OLD_ARGS, which is usually the result of breaking the command string arguments into 155254721Semaste// an array of space-separated strings, and searches through the arguments for any breakpoint ID range specifiers. 156254721Semaste// Any string in the array that is not part of an ID range specifier is copied directly into NEW_ARGS. If any 157254721Semaste// ID range specifiers are found, the range is interpreted and a list of canonical breakpoint IDs corresponding to 158254721Semaste// all the current breakpoints and locations in the range are added to NEW_ARGS. When this function is done, 159254721Semaste// NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range. 160254721Semaste 161254721Semastevoid 162254721SemasteBreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, 163254721Semaste Args &new_args) 164254721Semaste{ 165254721Semaste std::string range_start; 166254721Semaste const char *range_end; 167254721Semaste const char *current_arg; 168254721Semaste const size_t num_old_args = old_args.GetArgumentCount(); 169254721Semaste 170254721Semaste for (size_t i = 0; i < num_old_args; ++i) 171254721Semaste { 172254721Semaste bool is_range = false; 173254721Semaste current_arg = old_args.GetArgumentAtIndex (i); 174254721Semaste 175254721Semaste size_t range_start_len = 0; 176254721Semaste size_t range_end_pos = 0; 177254721Semaste if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos)) 178254721Semaste { 179254721Semaste is_range = true; 180254721Semaste range_start.assign (current_arg, range_start_len); 181254721Semaste range_end = current_arg + range_end_pos; 182254721Semaste } 183254721Semaste else if ((i + 2 < num_old_args) 184254721Semaste && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1)) 185254721Semaste && BreakpointID::IsValidIDExpression (current_arg) 186254721Semaste && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2))) 187254721Semaste { 188254721Semaste range_start.assign (current_arg); 189254721Semaste range_end = old_args.GetArgumentAtIndex (i+2); 190254721Semaste is_range = true; 191254721Semaste i = i+2; 192254721Semaste } 193254721Semaste else 194254721Semaste { 195254721Semaste // See if user has specified id.* 196254721Semaste std::string tmp_str = old_args.GetArgumentAtIndex (i); 197254721Semaste size_t pos = tmp_str.find ('.'); 198254721Semaste if (pos != std::string::npos) 199254721Semaste { 200254721Semaste std::string bp_id_str = tmp_str.substr (0, pos); 201254721Semaste if (BreakpointID::IsValidIDExpression (bp_id_str.c_str()) 202254721Semaste && tmp_str[pos+1] == '*' 203254721Semaste && tmp_str.length() == (pos + 2)) 204254721Semaste { 205254721Semaste break_id_t bp_id; 206254721Semaste break_id_t bp_loc_id; 207254721Semaste 208254721Semaste BreakpointID::ParseCanonicalReference (bp_id_str.c_str(), &bp_id, &bp_loc_id); 209254721Semaste BreakpointSP breakpoint_sp = target->GetBreakpointByID (bp_id); 210254721Semaste if (! breakpoint_sp) 211254721Semaste { 212254721Semaste new_args.Clear(); 213254721Semaste result.AppendErrorWithFormat ("'%d' is not a valid breakpoint ID.\n", bp_id); 214254721Semaste result.SetStatus (eReturnStatusFailed); 215254721Semaste return; 216254721Semaste } 217254721Semaste const size_t num_locations = breakpoint_sp->GetNumLocations(); 218254721Semaste for (size_t j = 0; j < num_locations; ++j) 219254721Semaste { 220254721Semaste BreakpointLocation *bp_loc = breakpoint_sp->GetLocationAtIndex(j).get(); 221254721Semaste StreamString canonical_id_str; 222254721Semaste BreakpointID::GetCanonicalReference (&canonical_id_str, bp_id, bp_loc->GetID()); 223254721Semaste new_args.AppendArgument (canonical_id_str.GetData()); 224254721Semaste } 225254721Semaste } 226254721Semaste 227254721Semaste } 228254721Semaste } 229254721Semaste 230254721Semaste if (is_range) 231254721Semaste { 232254721Semaste break_id_t start_bp_id; 233254721Semaste break_id_t end_bp_id; 234254721Semaste break_id_t start_loc_id; 235254721Semaste break_id_t end_loc_id; 236254721Semaste 237254721Semaste BreakpointID::ParseCanonicalReference (range_start.c_str(), &start_bp_id, &start_loc_id); 238254721Semaste BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id); 239254721Semaste 240254721Semaste if ((start_bp_id == LLDB_INVALID_BREAK_ID) 241254721Semaste || (! target->GetBreakpointByID (start_bp_id))) 242254721Semaste { 243254721Semaste new_args.Clear(); 244254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start.c_str()); 245254721Semaste result.SetStatus (eReturnStatusFailed); 246254721Semaste return; 247254721Semaste } 248254721Semaste 249254721Semaste if ((end_bp_id == LLDB_INVALID_BREAK_ID) 250254721Semaste || (! target->GetBreakpointByID (end_bp_id))) 251254721Semaste { 252254721Semaste new_args.Clear(); 253254721Semaste result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end); 254254721Semaste result.SetStatus (eReturnStatusFailed); 255254721Semaste return; 256254721Semaste } 257254721Semaste 258254721Semaste 259254721Semaste if (((start_loc_id == LLDB_INVALID_BREAK_ID) 260254721Semaste && (end_loc_id != LLDB_INVALID_BREAK_ID)) 261254721Semaste || ((start_loc_id != LLDB_INVALID_BREAK_ID) 262254721Semaste && (end_loc_id == LLDB_INVALID_BREAK_ID))) 263254721Semaste { 264254721Semaste new_args.Clear (); 265254721Semaste result.AppendErrorWithFormat ("Invalid breakpoint id range: Either both ends of range must specify" 266254721Semaste " a breakpoint location, or neither can specify a breakpoint location.\n"); 267254721Semaste result.SetStatus (eReturnStatusFailed); 268254721Semaste return; 269254721Semaste } 270254721Semaste 271254721Semaste // We have valid range starting & ending breakpoint IDs. Go through all the breakpoints in the 272254721Semaste // target and find all the breakpoints that fit into this range, and add them to new_args. 273254721Semaste 274254721Semaste // Next check to see if we have location id's. If so, make sure the start_bp_id and end_bp_id are 275254721Semaste // for the same breakpoint; otherwise we have an illegal range: breakpoint id ranges that specify 276254721Semaste // bp locations are NOT allowed to cross major bp id numbers. 277254721Semaste 278254721Semaste if ((start_loc_id != LLDB_INVALID_BREAK_ID) 279254721Semaste || (end_loc_id != LLDB_INVALID_BREAK_ID)) 280254721Semaste { 281254721Semaste if (start_bp_id != end_bp_id) 282254721Semaste { 283254721Semaste new_args.Clear(); 284254721Semaste result.AppendErrorWithFormat ("Invalid range: Ranges that specify particular breakpoint locations" 285254721Semaste " must be within the same major breakpoint; you specified two" 286254721Semaste " different major breakpoints, %d and %d.\n", 287254721Semaste start_bp_id, end_bp_id); 288254721Semaste result.SetStatus (eReturnStatusFailed); 289254721Semaste return; 290254721Semaste } 291254721Semaste } 292254721Semaste 293254721Semaste const BreakpointList& breakpoints = target->GetBreakpointList(); 294254721Semaste const size_t num_breakpoints = breakpoints.GetSize(); 295254721Semaste for (size_t j = 0; j < num_breakpoints; ++j) 296254721Semaste { 297254721Semaste Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex (j).get(); 298254721Semaste break_id_t cur_bp_id = breakpoint->GetID(); 299254721Semaste 300254721Semaste if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id)) 301254721Semaste continue; 302254721Semaste 303254721Semaste const size_t num_locations = breakpoint->GetNumLocations(); 304254721Semaste 305254721Semaste if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID)) 306254721Semaste { 307254721Semaste for (size_t k = 0; k < num_locations; ++k) 308254721Semaste { 309254721Semaste BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); 310254721Semaste if ((bp_loc->GetID() >= start_loc_id) && (bp_loc->GetID() <= end_loc_id)) 311254721Semaste { 312254721Semaste StreamString canonical_id_str; 313254721Semaste BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); 314254721Semaste new_args.AppendArgument (canonical_id_str.GetData()); 315254721Semaste } 316254721Semaste } 317254721Semaste } 318254721Semaste else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID)) 319254721Semaste { 320254721Semaste for (size_t k = 0; k < num_locations; ++k) 321254721Semaste { 322254721Semaste BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); 323254721Semaste if (bp_loc->GetID() <= end_loc_id) 324254721Semaste { 325254721Semaste StreamString canonical_id_str; 326254721Semaste BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); 327254721Semaste new_args.AppendArgument (canonical_id_str.GetData()); 328254721Semaste } 329254721Semaste } 330254721Semaste } 331254721Semaste else 332254721Semaste { 333254721Semaste StreamString canonical_id_str; 334254721Semaste BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID); 335254721Semaste new_args.AppendArgument (canonical_id_str.GetData()); 336254721Semaste } 337254721Semaste } 338254721Semaste } 339254721Semaste else // else is_range was false 340254721Semaste { 341254721Semaste new_args.AppendArgument (current_arg); 342254721Semaste } 343254721Semaste } 344254721Semaste 345254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 346254721Semaste return; 347254721Semaste} 348254721Semaste 349254721Semastebool 350254721SemasteBreakpointIDList::StringContainsIDRangeExpression (const char *in_string, 351254721Semaste size_t *range_start_len, 352254721Semaste size_t *range_end_pos) 353254721Semaste{ 354254721Semaste bool is_range_expression = false; 355254721Semaste std::string arg_str = in_string; 356254721Semaste std::string::size_type idx; 357254721Semaste std::string::size_type start_pos = 0; 358254721Semaste 359254721Semaste *range_start_len = 0; 360254721Semaste *range_end_pos = 0; 361254721Semaste 362254721Semaste int specifiers_size = 0; 363254721Semaste for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i) 364254721Semaste ++specifiers_size; 365254721Semaste 366254721Semaste for (int i = 0; i < specifiers_size && !is_range_expression; ++i) 367254721Semaste { 368254721Semaste const char *specifier_str = BreakpointID::g_range_specifiers[i]; 369254721Semaste size_t len = strlen (specifier_str); 370254721Semaste idx = arg_str.find (BreakpointID::g_range_specifiers[i]); 371254721Semaste if (idx != std::string::npos) 372254721Semaste { 373254721Semaste *range_start_len = idx - start_pos; 374254721Semaste std::string start_str = arg_str.substr (start_pos, *range_start_len); 375254721Semaste if (idx + len < arg_str.length()) 376254721Semaste { 377254721Semaste *range_end_pos = idx + len; 378254721Semaste std::string end_str = arg_str.substr (*range_end_pos); 379254721Semaste if (BreakpointID::IsValidIDExpression (start_str.c_str()) 380254721Semaste && BreakpointID::IsValidIDExpression (end_str.c_str())) 381254721Semaste { 382254721Semaste is_range_expression = true; 383254721Semaste //*range_start = start_str; 384254721Semaste //*range_end = end_str; 385254721Semaste } 386254721Semaste } 387254721Semaste } 388254721Semaste } 389254721Semaste 390254721Semaste if (!is_range_expression) 391254721Semaste { 392254721Semaste *range_start_len = 0; 393254721Semaste *range_end_pos = 0; 394254721Semaste } 395254721Semaste 396254721Semaste return is_range_expression; 397254721Semaste} 398