1 //===-- BreakpointIDList.cpp ------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Breakpoint/BreakpointIDList.h" 11 12 #include "lldb/Breakpoint/Breakpoint.h" 13 #include "lldb/Breakpoint/BreakpointLocation.h" 14 #include "lldb/Interpreter/CommandReturnObject.h" 15 #include "lldb/Core/Args.h" 16 #include "lldb/Target/Target.h" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 21 //---------------------------------------------------------------------- 22 // class BreakpointIDList 23 //---------------------------------------------------------------------- 24 25 BreakpointIDList::BreakpointIDList () : 26 m_invalid_id (LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID) 27 { 28 } 29 30 BreakpointIDList::~BreakpointIDList () 31 { 32 } 33 34 int 35 BreakpointIDList::Size() 36 { 37 return m_breakpoint_ids.size(); 38 } 39 40 BreakpointID & 41 BreakpointIDList::GetBreakpointIDAtIndex (int index) 42 { 43 if (index < m_breakpoint_ids.size()) 44 return m_breakpoint_ids[index]; 45 else 46 return m_invalid_id; 47 } 48 49 bool 50 BreakpointIDList::RemoveBreakpointIDAtIndex (int index) 51 { 52 bool success = false; 53 if (index < m_breakpoint_ids.size()) 54 { 55 BreakpointIDArray::iterator pos; 56 int i; 57 58 for (pos = m_breakpoint_ids.begin(), i = 0; i != index && pos != m_breakpoint_ids.end(); ++pos, ++i); 59 assert (i == index); 60 if (pos != m_breakpoint_ids.end()) 61 { 62 m_breakpoint_ids.erase (pos); 63 success = true; 64 } 65 } 66 return success; 67 } 68 69 void 70 BreakpointIDList::Clear() 71 { 72 m_breakpoint_ids.clear (); 73 } 74 75 bool 76 BreakpointIDList::AddBreakpointID (BreakpointID bp_id) 77 { 78 m_breakpoint_ids.push_back (bp_id); 79 80 return true; // We don't do any verification in this function, so always return true. 81 } 82 83 bool 84 BreakpointIDList::AddBreakpointID (const char *bp_id_str) 85 { 86 BreakpointID temp_bp_id; 87 break_id_t bp_id; 88 break_id_t loc_id; 89 90 bool success = BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id); 91 92 if (success) 93 { 94 temp_bp_id.SetID (bp_id, loc_id); 95 m_breakpoint_ids.push_back (temp_bp_id); 96 } 97 98 return success; 99 } 100 101 bool 102 BreakpointIDList::FindBreakpointID (BreakpointID &bp_id, int *position) 103 { 104 bool success = false; 105 BreakpointIDArray::iterator tmp_pos; 106 107 for (int i = 0; i < m_breakpoint_ids.size(); ++i) 108 { 109 BreakpointID tmp_id = m_breakpoint_ids[i]; 110 if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID() 111 && tmp_id.GetLocationID() == bp_id.GetLocationID()) 112 { 113 success = true; 114 *position = i; 115 return true; 116 } 117 } 118 119 return false; 120 } 121 122 bool 123 BreakpointIDList::FindBreakpointID (const char *bp_id_str, int *position) 124 { 125 BreakpointID temp_bp_id; 126 break_id_t bp_id; 127 break_id_t loc_id; 128 129 if (BreakpointID::ParseCanonicalReference (bp_id_str, &bp_id, &loc_id)) 130 { 131 temp_bp_id.SetID (bp_id, loc_id); 132 return FindBreakpointID (temp_bp_id, position); 133 } 134 else 135 return false; 136 } 137 138 void 139 BreakpointIDList::InsertStringArray (const char **string_array, int array_size, CommandReturnObject &result) 140 { 141 if (string_array == NULL) 142 return; 143 144 for (int i = 0; i < array_size; ++i) 145 { 146 break_id_t bp_id; 147 break_id_t loc_id; 148 149 if (BreakpointID::ParseCanonicalReference (string_array[i], &bp_id, &loc_id)) 150 { 151 if (bp_id != LLDB_INVALID_BREAK_ID) 152 { 153 BreakpointID temp_bp_id(bp_id, loc_id); 154 m_breakpoint_ids.push_back (temp_bp_id); 155 } 156 else 157 { 158 result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", string_array[i]); 159 result.SetStatus (eReturnStatusFailed); 160 return; 161 } 162 } 163 } 164 result.SetStatus (eReturnStatusSuccessFinishNoResult); 165 } 166 167 168 // This function takes OLD_ARGS, which is usually the result of breaking the command string arguments into 169 // an array of space-separated strings, and searches through the arguments for any breakpoint ID range specifiers. 170 // Any string in the array that is not part of an ID range specifier is copied directly into NEW_ARGS. If any 171 // ID range specifiers are found, the range is interpreted and a list of canonical breakpoint IDs corresponding to 172 // all the current breakpoints and locations in the range are added to NEW_ARGS. When this function is done, 173 // NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced by the members of the range. 174 175 void 176 BreakpointIDList::FindAndReplaceIDRanges (Args &old_args, Target *target, CommandReturnObject &result, 177 Args &new_args) 178 { 179 char *range_start; 180 const char *range_end; 181 const char *current_arg; 182 int num_old_args = old_args.GetArgumentCount(); 183 184 for (int i = 0; i < num_old_args; ++i) 185 { 186 bool is_range = false; 187 current_arg = old_args.GetArgumentAtIndex (i); 188 189 int range_start_len = 0; 190 int range_end_pos = 0; 191 if (BreakpointIDList::StringContainsIDRangeExpression (current_arg, &range_start_len, &range_end_pos)) 192 { 193 is_range = true; 194 range_start = (char *) malloc (range_start_len + 1); 195 strncpy (range_start, current_arg, range_start_len); 196 range_start[range_start_len] = '\0'; 197 range_end = current_arg + range_end_pos; 198 } 199 else if ((i + 2 < num_old_args) 200 && BreakpointID::IsRangeIdentifier (old_args.GetArgumentAtIndex (i+1)) 201 && BreakpointID::IsValidIDExpression (current_arg) 202 && BreakpointID::IsValidIDExpression (old_args.GetArgumentAtIndex (i+2))) 203 { 204 range_start = (char *) current_arg; 205 range_end = old_args.GetArgumentAtIndex (i+2); 206 is_range = true; 207 i = i+2; 208 } 209 210 if (is_range) 211 { 212 break_id_t start_bp_id; 213 break_id_t end_bp_id; 214 break_id_t start_loc_id; 215 break_id_t end_loc_id; 216 217 BreakpointID::ParseCanonicalReference (range_start, &start_bp_id, &start_loc_id); 218 BreakpointID::ParseCanonicalReference (range_end, &end_bp_id, &end_loc_id); 219 220 if ((start_bp_id == LLDB_INVALID_BREAK_ID) 221 || (! target->GetBreakpointByID (start_bp_id))) 222 { 223 new_args.Clear(); 224 result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_start); 225 result.SetStatus (eReturnStatusFailed); 226 return; 227 } 228 229 if ((end_bp_id == LLDB_INVALID_BREAK_ID) 230 || (! target->GetBreakpointByID (end_bp_id))) 231 { 232 new_args.Clear(); 233 result.AppendErrorWithFormat ("'%s' is not a valid breakpoint ID.\n", range_end); 234 result.SetStatus (eReturnStatusFailed); 235 return; 236 } 237 238 // We have valid range starting & ending breakpoint IDs. Go through all the breakpoints in the 239 // target and find all the breakpoints that fit into this range, and add them to new_args. 240 241 const BreakpointList& breakpoints = target->GetBreakpointList(); 242 size_t num_breakpoints = breakpoints.GetSize(); 243 for (int j = 0; j < num_breakpoints; ++j) 244 { 245 Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (j).get(); 246 break_id_t cur_bp_id = breakpoint->GetID(); 247 248 if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id)) 249 continue; 250 251 size_t num_locations = breakpoint->GetNumLocations(); 252 253 if ((cur_bp_id == start_bp_id) && (start_loc_id != LLDB_INVALID_BREAK_ID)) 254 { 255 for (int k = 0; k < num_locations; ++k) 256 { 257 BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); 258 if (bp_loc->GetID() >= start_loc_id) 259 { 260 StreamString canonical_id_str; 261 BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); 262 new_args.AppendArgument (canonical_id_str.GetData()); 263 } 264 } 265 } 266 else if ((cur_bp_id == end_bp_id) && (end_loc_id != LLDB_INVALID_BREAK_ID)) 267 { 268 for (int k = 0; k < num_locations; ++k) 269 { 270 BreakpointLocation * bp_loc = breakpoint->GetLocationAtIndex(k).get(); 271 if (bp_loc->GetID() <= end_loc_id) 272 { 273 StreamString canonical_id_str; 274 BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, bp_loc->GetID()); 275 new_args.AppendArgument (canonical_id_str.GetData()); 276 } 277 } 278 } 279 else 280 { 281 StreamString canonical_id_str; 282 BreakpointID::GetCanonicalReference (&canonical_id_str, cur_bp_id, LLDB_INVALID_BREAK_ID); 283 new_args.AppendArgument (canonical_id_str.GetData()); 284 } 285 } 286 } 287 else // else is_range was false 288 { 289 new_args.AppendArgument (current_arg); 290 } 291 } 292 293 result.SetStatus (eReturnStatusSuccessFinishNoResult); 294 return; 295 } 296 297 //bool 298 //BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, const char **range_start, 299 // const **range_end) 300 bool 301 BreakpointIDList::StringContainsIDRangeExpression (const char *in_string, int *range_start_len, int *range_end_pos) 302 { 303 bool is_range_expression = false; 304 std::string arg_str = in_string; 305 std::string::size_type idx; 306 std::string::size_type start_pos = 0; 307 308 //*range_start = NULL; 309 //*range_end = NULL; 310 *range_start_len = 0; 311 *range_end_pos = 0; 312 313 int specifiers_size = 0; 314 for (int i = 0; BreakpointID::g_range_specifiers[i] != NULL; ++i) 315 ++specifiers_size; 316 317 for (int i = 0; i < specifiers_size && !is_range_expression; ++i) 318 { 319 const char *specifier_str = BreakpointID::g_range_specifiers[i]; 320 int len = strlen (specifier_str); 321 idx = arg_str.find (BreakpointID::g_range_specifiers[i]); 322 if (idx != std::string::npos) 323 { 324 *range_start_len = idx - start_pos; 325 std::string start_str = arg_str.substr (start_pos, *range_start_len); 326 if (idx + len < arg_str.length()) 327 { 328 *range_end_pos = idx + len; 329 std::string end_str = arg_str.substr (*range_end_pos); 330 if (BreakpointID::IsValidIDExpression (start_str.c_str()) 331 && BreakpointID::IsValidIDExpression (end_str.c_str())) 332 { 333 is_range_expression = true; 334 //*range_start = start_str; 335 //*range_end = end_str; 336 } 337 } 338 } 339 } 340 341 if (!is_range_expression) 342 { 343 *range_start_len = 0; 344 *range_end_pos = 0; 345 } 346 347 return is_range_expression; 348 } 349