protected override void ProcessRecord() { ulong addr; if (0 != Address) { addr = Address; Util.Assert((c_Address_ScriptBlockCommand_ParamSet == this.ParameterSetName) || (c_Address_DbgEngCommand_ParamSet == this.ParameterSetName)); Expression = DbgProvider.FormatAddress(Address, Debugger.TargetIs32Bit, true).ToString(false); } else { if (DbgProvider.TryParseHexOrDecimalNumber(Expression, out addr)) { // Oh... PowerShell might have interpreted a backtick as an escape... // Let's fix it. Expression = DbgProvider.FormatAddress(addr, Debugger.TargetIs32Bit, true).ToString(false); } } if (0 != addr) { _CreateBp(addr); return; } // // We have a symbolic expression. Dbgeng may or may not like it. // // For instance, if it resolves to a function that got inlined, even if // there is only a single match, dbgeng will complain and say "please use // bm instead". // // I hate that, so we're just going to try tohandle the symbol lookup // ourselves. Also, it seems there isn't actually a way to do a "bm" // breakpoint via the API. // IList <ulong> addrs = _TryResolveExpression(); if (null != addrs) { // We may not actually have been able to resolve the expression, but it // wasn't obviously bad, in which case we'll have to set a deferred // breakpoint. if (0 == addrs.Count) { _CreateDeferredBp(); } else { foreach (ulong bpAddr in addrs) { Util.Assert(0 != bpAddr); _CreateBp(bpAddr); } } } } // end ProcessRecord()
private ColorString FormatRGB(uint numColumns, bool withAlpha) { var bytes = Memory.Bytes; bool is32Bit = Debugger.TargetIs32Bit; ulong startAddress = Memory.StartAddress; if (0 == numColumns) { numColumns = 64; } ColorString cs = new ColorString(); var bytesPerCharacter = withAlpha ? 4 : 3; int bytesPerRow = (int)numColumns * bytesPerCharacter + 3 & ~(3); //round up for (int rowStart = 0; rowStart + bytesPerCharacter < bytes.Count; rowStart += bytesPerRow) { if (rowStart != 0) { cs.AppendLine(); } cs.Append(DbgProvider.FormatAddress(startAddress + (uint)rowStart, is32Bit, true, true)).Append(" "); var rowLen = Math.Min(bytes.Count - rowStart, bytesPerRow); for (int colOffset = 0; colOffset + bytesPerCharacter < rowLen; colOffset += bytesPerCharacter) { byte b = bytes[rowStart + colOffset + 0]; byte g = bytes[rowStart + colOffset + 1]; byte r = bytes[rowStart + colOffset + 2]; string ch = "█"; if (withAlpha) { ch = AlphaChars[bytes[rowStart + colOffset + 3] >> 6]; } cs.AppendFgRgb(r, g, b, ch); } } return(cs.MakeReadOnly()); }
} // end ProcessRecord() private void _UnassembleInstructions(ulong addr, Func <ulong, bool> keepGoing) { ColorString csBlockId; try { ulong disp; var addrName = Debugger.GetNameByOffset(addr, out disp); csBlockId = DbgProvider.ColorizeSymbol(addrName); if (0 != disp) { csBlockId.Append(Util.Sprintf("+{0:x}", disp)); } } catch (DbgEngException) { // Ignore. We'll just use the address as the block id. If we really can't // get the memory there, we'll fail with a good error message later. csBlockId = new ColorString().Append(DbgProvider.FormatAddress(addr, Debugger.TargetIs32Bit, true)); } csBlockId.Append(":").MakeReadOnly(); bool hasCodeBytes = !Debugger.AssemblyOptions.HasFlag(DbgAssemblyOptions.NoCodeBytes); while (keepGoing(addr)) { ulong tmpAddr = addr; string disasm = Debugger.Disassemble(tmpAddr, out addr).Trim(); WriteObject(_ParseDisassembly(tmpAddr, disasm, csBlockId, hasCodeBytes)); } DbgProvider.SetAutoRepeatCommand(Util.Sprintf("{0} -Address 0x{1} -InstructionCount {2}", MyInvocation.InvocationName, addr.ToString("x"), InstructionCount)); NextAddrToDisassemble = addr; } // end _UnassembleInstructions()
/// <summary> /// This method is "best effort"--it probably won't screen out all possible /// invalid breakpoints. But it should hopefully catch some obviously bad ones. /// </summary> private void _TryValidateBp(ref DbgBreakpointInfo bp) { bool bpIsActuallyBogus = false; if (bp.IsEnabled) { if (bp.IsDeferred) { try { Util.Assert(!String.IsNullOrEmpty(Expression)); // TODO: What if the expression is not a symbol?? string mod, bareSym; ulong offset; DbgProvider.ParseSymbolName(Expression, out mod, out bareSym, out offset); if ("*" == mod) { bpIsActuallyBogus = true; } else { var modInfos = Debugger.GetModuleByName(mod).ToArray(); if (modInfos.Length > 0) { // The module is loaded and yet the bp is deferred... the // expression is no good. // // Or there is more than one module with that name. bpIsActuallyBogus = true; } } } catch (ArgumentException ae) { LogManager.Trace("Failed to parse expression as a symbol: {0}", Util.GetExceptionMessages(ae)); } } // end if( bp is deferred ) else if (0 != bp.Offset) { // The address shouldn't be invalid, because that would indicate the // bp is deferred, but we already checked for that. Util.Assert(bp.Offset != DebuggerObject.InvalidAddress); MEMORY_BASIC_INFORMATION64 mbi; int hr = Debugger.TryQueryVirtual(bp.Offset, out mbi); if (hr != 0) { // iDNA targets don't yet handle QueryVirtual. if (hr != DebuggerObject.E_NOTIMPL) { LogManager.Trace("_TryValidateBp: TryQueryVirtual failed: {0}", Util.FormatErrorCode(hr)); bpIsActuallyBogus = true; } } else { if ((mbi.Protect != PAGE.EXECUTE) && (mbi.Protect != PAGE.EXECUTE_READ) && // <-- (mbi.Protect != PAGE.EXECUTE_READWRITE) && // <-- I don't actually know what these are (mbi.Protect != PAGE.EXECUTE_WRITECOPY)) // <-- { bpIsActuallyBogus = true; } } } } // end if( bp is enabled ) if (bpIsActuallyBogus) { ulong addr = 0; if ((bp.Offset != 0) && (bp.Offset != DebuggerObject.InvalidAddress)) { addr = bp.Offset; } Debugger.RemoveBreakpoint(ref bp); var dpe = new DbgProviderException(Util.Sprintf("Failed to set breakpoint at {0}.", addr != 0 ? DbgProvider.FormatAddress(addr, Debugger.TargetIs32Bit, true).ToString(false) : Expression), "BpEnabledButDeferredAndOrBad", ErrorCategory.InvalidArgument, addr != 0 ? (object)addr : (object)Expression); try { throw dpe; } catch { } // give it a stack WriteError(dpe); } } // end _TryValidateBp()