protected override BreakEventInfo OnInsertBreakEvent (BreakEvent ev)
		{
			if (exited)
				return null;

			var bi = new BreakInfo ();
			
			if (ev is FunctionBreakpoint) {
				var fb = (FunctionBreakpoint) ev;
				bool generic;
				
				bi.Location = FindLocationByFunction (fb.FunctionName, fb.ParamTypes, fb.Line, out generic);
				if (bi.Location != null) {
					fb.SetResolvedFileName (bi.Location.SourceFile);
					bi.FileName = fb.FileName;
					
					InsertBreakpoint (fb, bi);
					bi.SetStatus (BreakEventStatus.Bound, null);
					
					// Note: if the type or method is generic, there may be more instances so don't assume we are done resolving the breakpoint
					if (generic)
						pending_bes.Add (bi);
				} else {
					int dot = fb.FunctionName.LastIndexOf ('.');
					if (dot != -1)
						bi.TypeName = fb.FunctionName.Substring (0, dot);
					
					pending_bes.Add (bi);
					bi.SetStatus (BreakEventStatus.NotBound, null);
				}
			} else if (ev is Breakpoint) {
				var bp = (Breakpoint) ev;
				bool insideLoadedRange;
				bool generic;
				
				bi.Location = FindLocationByFile (bp.FileName, bp.Line, out generic, out insideLoadedRange);
				bi.FileName = bp.FileName;
				
				if (bi.Location != null) {
					InsertBreakpoint (bp, bi);
					bi.SetStatus (BreakEventStatus.Bound, null);
					
					// Note: if the type or method is generic, there may be more instances so don't assume we are done resolving the breakpoint
					if (generic)
						pending_bes.Add (bi);
				} else {
					pending_bes.Add (bi);
					if (insideLoadedRange)
						bi.SetStatus (BreakEventStatus.Invalid, null);
					else
						bi.SetStatus (BreakEventStatus.NotBound, null);
				}
			} else if (ev is Catchpoint) {
				var cp = (Catchpoint) ev;
				TypeMirror type;

				if (!types.TryGetValue (cp.ExceptionName, out type)) {
					//
					// Same as in FindLocationByFile (), fetch types matching the type name
					if (vm.Version.AtLeast (2, 9)) {
						foreach (TypeMirror t in vm.GetTypes (cp.ExceptionName, false))
							ProcessType (t);
					}
				}
				
				if (types.TryGetValue (cp.ExceptionName, out type)) {
					InsertCatchpoint (cp, bi, type);
					bi.SetStatus (BreakEventStatus.Bound, null);
				} else {
					bi.TypeName = cp.ExceptionName;
					pending_bes.Add (bi);
					bi.SetStatus (BreakEventStatus.NotBound, null);
				}
			}

			/*
			 * TypeLoad events lead to too much wire traffic + suspend/resume work, so
			 * filter them using the file names used by pending breakpoints.
			 */
			if (vm.Version.AtLeast (2, 9)) {
				var sourceFileList = pending_bes.Where (b => b.FileName != null).Select (b => b.FileName).ToArray ();
				if (sourceFileList.Length > 0) {
					//HACK: explicitly try lowercased drivename on windows, since csc (when not hosted in VS) lowercases
					//the drivename in the pdb files that get converted to mdbs as-is
					//FIXME: we should really do a case-insensitive request on Win/Mac, when sdb supports that
					if (IsWindows) {
						int originalCount = sourceFileList.Length;
						Array.Resize (ref sourceFileList, originalCount * 2);
						for (int i = 0; i < originalCount; i++) {
							string n = sourceFileList[i];
							sourceFileList[originalCount + i] = char.ToLower (n[0]) + n.Substring (1);
						}
					}
					
					if (typeLoadReq == null) {
						typeLoadReq = vm.CreateTypeLoadRequest ();
					}
					typeLoadReq.Enabled = false;
					typeLoadReq.SourceFileFilter = sourceFileList;
					typeLoadReq.Enabled = true;
				}
				
				var typeNameList = pending_bes.Where (b => b.TypeName != null).Select (b => b.TypeName).ToArray ();
				if (typeNameList.Length > 0) {
					// Use a separate request since the filters are ANDed together
					if (typeLoadTypeNameReq == null) {
						typeLoadTypeNameReq = vm.CreateTypeLoadRequest ();
					}
					typeLoadTypeNameReq.Enabled = false;
					typeLoadTypeNameReq.TypeNameFilter = typeNameList;
					typeLoadTypeNameReq.Enabled = true;
				}
			}

			return bi;
		}
		protected override BreakEventInfo OnInsertBreakEvent (BreakEvent ev)
		{
			if (exited)
				return null;

			var bi = new BreakInfo ();
			
			if (ev is Breakpoint) {
				var bp = (Breakpoint) ev;
				bool inisideLoadedRange;
				bi.FileName = bp.FileName;
				bi.Location = FindLocation (bp.FileName, bp.Line, out inisideLoadedRange);
				if (bi.Location != null) {
					InsertBreakpoint (bp, bi);
					bi.SetStatus (BreakEventStatus.Bound, null);
				}
				else {
					pending_bes.Add (bi);
					if (inisideLoadedRange)
						bi.SetStatus (BreakEventStatus.Invalid, null);
					else
						bi.SetStatus (BreakEventStatus.NotBound, null);
				}
			} else if (ev is Catchpoint) {
				var cp = (Catchpoint) ev;
				TypeMirror type;

				if (!types.TryGetValue (cp.ExceptionName, out type)) {
					//
					// Same as in FindLocation (), fetch types matching the type name
					if (vm.Version.AtLeast (2, 9)) {
						foreach (TypeMirror t in vm.GetTypes (cp.ExceptionName, false))
							ProcessType (t);
					}
				}
				if (types.TryGetValue (cp.ExceptionName, out type)) {
					InsertCatchpoint (cp, bi, type);
					bi.SetStatus (BreakEventStatus.Bound, null);
				} else {
					bi.ExceptionName = cp.ExceptionName;
					pending_bes.Add (bi);
					bi.SetStatus (BreakEventStatus.NotBound, null);
				}
			}

			/*
			 * TypeLoad events lead to too much wire traffic + suspend/resume work, so
			 * filter them using the file names used by pending breakpoints.
			 */
			if (vm.Version.AtLeast (2, 9)) {
				var sourceFileList = pending_bes.Where (b => b.FileName != null).Select (b => b.FileName).ToArray ();
				if (sourceFileList.Length > 0) {
					if (typeLoadReq == null) {
						typeLoadReq = vm.CreateTypeLoadRequest ();
					}
					typeLoadReq.Enabled = false;
					typeLoadReq.SourceFileFilter = sourceFileList;
					typeLoadReq.Enabled = true;
				}
				var typeNameList = pending_bes.Where (b => b.ExceptionName != null).Select (b => b.ExceptionName).ToArray ();
				if (typeNameList.Length > 0) {
					// Use a separate request since the filters are ANDed together
					if (typeLoadTypeNameReq == null) {
						typeLoadTypeNameReq = vm.CreateTypeLoadRequest ();
					}
					typeLoadTypeNameReq.Enabled = false;
					typeLoadTypeNameReq.TypeNameFilter = typeNameList;
					typeLoadTypeNameReq.Enabled = true;
				}
			}

			return bi;
		}