internal async Task <VariableInformation> CreateMIDebuggerVariable(ThreadContext ctx, AD7Engine engine, AD7Thread thread) { VariableInformation vi = new VariableInformation(Name, ctx, engine, thread, IsParameter); await vi.Eval(); return(vi); }
//this constructor is private because it should only be used internally to create children private VariableInformation(TupleValue results, VariableInformation parent) : this(parent._ctx, parent._engine, parent.Client) { TypeName = results.TryFindString("type"); Value = results.TryFindString("value"); Name = results.FindString("exp"); CountChildren = results.FindUint("numchild"); int index; if (!results.Contains("value") && (Name == TypeName || Name.Contains("::"))) { // base classes show up with no value and exp==type // (sometimes underlying debugger does not follow this convention, when using typedefs in templated types so look for "::" in the field name too) Name = "base"; Value = TypeName; VariableNodeType = NodeType.BaseClass; } else if (Int32.TryParse(this.Name, System.Globalization.NumberStyles.Integer, null, out index)) // array element { Name = '[' + this.Name + ']'; VariableNodeType = NodeType.ArrayElement; } else { _strippedName = Name; VariableNodeType = NodeType.Field; } _internalName = results.FindString("name"); IsChild = true; _format = parent._format; // inherit formatting _parent = parent.VariableNodeType == NodeType.AccessQualifier ? parent._parent : parent; }
//this constructor is used to create modified expressions from a parent internal VariableInformation(string expr, VariableInformation parent) : this(parent._ctx, parent._engine, parent.Client) { // strip off formatting string _strippedName = StripFormatSpecifier(expr, out _format); Name = expr; VariableNodeType = NodeType.Root; }
//this constructor is private because it should only be used internally to create children private VariableInformation(TupleValue results, VariableInformation parent, string name = null) : this(parent._ctx, parent._engine, parent.Client) { TypeName = results.TryFindString("type"); Value = results.TryFindString("value"); Name = name ?? results.FindString("exp"); if (results.Contains("dynamic")) { CountChildren = 1; } else { CountChildren = results.FindUint("numchild"); } if (results.Contains("displayhint")) { DisplayHint = results.FindString("displayhint"); } if (results.Contains("attributes")) { if (results.FindString("attributes") == "noneditable") { _isReadonly = true; } _attribsFetched = true; } int index; if (!results.Contains("value") && (Name == TypeName || Name.Contains("::"))) { // base classes show up with no value and exp==type // (sometimes underlying debugger does not follow this convention, when using typedefs in templated types so look for "::" in the field name too) Name = TypeName + " (base)"; Value = TypeName; VariableNodeType = NodeType.BaseClass; } else if (Int32.TryParse(this.Name, System.Globalization.NumberStyles.Integer, null, out index)) // array element { Name = '[' + this.Name + ']'; VariableNodeType = NodeType.ArrayElement; } else if (this.Name.Length > 2 && this.Name[0] == '[' && this.Name[this.Name.Length - 1] == ']') { VariableNodeType = NodeType.ArrayElement; } else { _strippedName = Name; VariableNodeType = NodeType.Field; } _internalName = results.FindString("name"); IsChild = true; _format = parent._format; // inherit formatting _parent = parent.VariableNodeType == NodeType.AccessQualifier ? parent._parent : parent; this.PropertyInfoFlags = parent.PropertyInfoFlags; }
//This method gets the locals and parameters and creates an MI debugger variable for each one so that we can manipulate them (and expand children, etc.) //NOTE: Eval is called internal async Task <List <VariableInformation> > GetLocalsAndParameters(AD7Thread thread, ThreadContext ctx) { List <VariableInformation> variables = new List <VariableInformation>(); ValueListValue localsAndParameters = await MICommandFactory.StackListVariables(PrintValues.NoValues, thread.Id, ctx.Level); foreach (var localOrParamResult in localsAndParameters.Content) { string name = localOrParamResult.FindString("name"); bool isParam = localOrParamResult.TryFindString("arg") == "1"; SimpleVariableInformation simpleInfo = new SimpleVariableInformation(name, isParam); VariableInformation vi = await simpleInfo.CreateMIDebuggerVariable(ctx, Engine, thread); variables.Add(vi); } return(variables); }
public VariableInformation FindChildByName(string name) { EnsureChildren(); if (CountChildren == 0) { return(null); } Debug.Assert(Children != null, "Failed to find children"); VariableInformation var = Array.Find(Children, (c) => c.Name == name); if (var != null) { return(var); } VariableInformation baseChild = null; var = Array.Find(Children, (c) => c.VariableNodeType == NodeType.BaseClass && (baseChild = c.FindChildByName(name)) != null); return(baseChild); }
private async Task InternalFetchChildren() { Results results = await _engine.DebuggedProcess.CmdAsync(string.Format("-var-list-children --simple-values \"{0}\"", _internalName), ResultClass.None); if (results.ResultClass == ResultClass.done) { TupleValue[] children = results.Find <ResultListValue>("children").FindAll <TupleValue>("child"); int i = 0; bool isArray = IsArrayType(); bool elementIsReadonly = false; if (isArray) { CountChildren = results.FindUint("numchild"); Children = new VariableInformation[CountChildren]; //if (k.Length > 0) // perform attrib check on first array child, apply to all elements //{ // MICore.Debugger.Results childResults = MICore.Debugger.DecodeResults(k[0]); // string name = childResults.Find("name"); // Debug.Assert(!string.IsNullOrEmpty(name)); // string attribute = await m_engine.DebuggedProcess.MICommandFactory.VarShowAttributes(name); // elementIsReadonly = (attribute != "editable"); //} foreach (var c in children) { Children[i] = new VariableInformation(c, this, elementIsReadonly); i++; } } else { List <VariableInformation> listChildren = new List <VariableInformation>(); foreach (var c in children) { var variable = new VariableInformation(c, this); enum_DBG_ATTRIB_FLAGS access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_NONE; if (variable.Name == "public") { access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PUBLIC; variable.VariableNodeType = NodeType.AccessQualifier; } else if (variable.Name == "private") { access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PRIVATE; variable.VariableNodeType = NodeType.AccessQualifier; } else if (variable.Name == "protected") { access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PROTECTED; variable.VariableNodeType = NodeType.AccessQualifier; } if (access != enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_NONE) { // Add this child's children await variable.InternalFetchChildren(); foreach (var child in variable.Children) { ((VariableInformation)child).Access = access; listChildren.Add(child); } } else { listChildren.Add(variable); } } Children = listChildren.ToArray(); CountChildren = (uint)Children.Length; } } else { Children = new VariableInformation[0]; CountChildren = 0; } if (_format != null) { foreach (var child in Children) { await child.Format(); } } }
private VariableInformation(TupleValue results, VariableInformation parent, bool ro) : this(results, parent) { _attribsFetched = true; // read-only attribute is passed in at construction _isReadonly = ro; }
private void InitializeBytes() { if (_bytes != null) { return; } uint fetched = 0; _bytes = new byte[0]; IDebugMemoryContext2 memAddr; if (GetMemoryContext(out memAddr) != Constants.S_OK) { // no address in the expression value, try casting to a char* VariableInformation v = new VariableInformation("(char*)(" + _variableInformation.FullName() + ")", (VariableInformation)_variableInformation); v.SyncEval(); if (v.Error) { return; } AD7Property p = new AD7Property(_engine, v); uint pLen; if (p.GetStringCharLength(out pLen) == Constants.S_OK) { _bytes = new byte[pLen]; p.GetStringRawBytes(pLen, _bytes, out fetched); } return; } IDebugMemoryBytes2 memContent; if (((AD7MemoryAddress)memAddr).Engine.GetMemoryBytes(out memContent) != Constants.S_OK) { return; } fetched = 0; bool eos = false; byte[] bytes = new byte[s_maxChars + 1]; byte[] chunk = new byte[2048]; while (!eos) { // fetched is count of bytes in string so far // eos == false => fetch < s_maxChars // eos == true => string is terminated, that is bytes[fetched-1] == 0 uint bytesRead; uint bytesUnreadable = 0; // get next chunk if (memContent.ReadAt(memAddr, (uint)chunk.Length, chunk, out bytesRead, ref bytesUnreadable) != Constants.S_OK) { break; } // copy chunk to bytes for (uint i = 0; i < bytesRead; ++i) { bytes[fetched++] = chunk[i]; if (bytes[fetched - 1] == 0) { eos = true; // end of string break; } if (fetched == s_maxChars) // buffer is full { bytes[fetched++] = 0; // end the string eos = true; break; } } if (bytesRead != chunk.Length) { // read to end of available memory break; } // advance to next chunk memAddr.Add(bytesRead, out memAddr); } if (!eos) { Debug.Assert(fetched < bytes.Length); bytes[fetched++] = 0; } if (fetched < bytes.Length) { _bytes = new byte[fetched]; Array.Copy(bytes, _bytes, (int)fetched); } else { _bytes = bytes; } }
private async Task InternalFetchChildren() { this.VerifyNotDisposed(); Results results = await _engine.DebuggedProcess.MICommandFactory.VarListChildren(_internalName, PropertyInfoFlags, ResultClass.None); if (results.ResultClass == ResultClass.done) { TupleValue[] children = results.Contains("children") ? results.Find <ResultListValue>("children").FindAll <TupleValue>("child") : new TupleValue[0]; int i = 0; bool isArray = IsArrayType(); if (isArray) { CountChildren = results.FindUint("numchild"); Children = new VariableInformation[CountChildren]; foreach (var c in children) { Children[i] = new VariableInformation(c, this); i++; } } else if (IsMapType()) { // // support for gdb's pretty-printing built-in displayHint "map", from the gdb docs: // 'Indicate that the object being printed is “map-like”, and that the // children of this value can be assumed to alternate between keys and values.' // List <VariableInformation> listChildren = new List <VariableInformation>(); for (int p = 0; p + 1 < children.Length; p += 2) { // One Variable is created for each pair returned with the first element (p) being the name of the child // and the second element (p+1) becoming the value. string name = children[p].FindString("value"); var variable = new VariableInformation(children[p + 1], this, '[' + name + ']'); listChildren.Add(variable); } Children = listChildren.ToArray(); CountChildren = (uint)Children.Length; } else { List <VariableInformation> listChildren = new List <VariableInformation>(); foreach (var c in children) { var variable = new VariableInformation(c, this); enum_DBG_ATTRIB_FLAGS access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_NONE; if (variable.Name == "public") { access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PUBLIC; variable.VariableNodeType = NodeType.AccessQualifier; } else if (variable.Name == "private") { access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PRIVATE; variable.VariableNodeType = NodeType.AccessQualifier; } else if (variable.Name == "protected") { access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ACCESS_PROTECTED; variable.VariableNodeType = NodeType.AccessQualifier; } if (access != enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_NONE) { // Add this child's children await variable.InternalFetchChildren(); foreach (var child in variable.Children) { ((VariableInformation)child).Access = access; listChildren.Add(child); } } else { listChildren.Add(variable); } } Children = listChildren.ToArray(); CountChildren = (uint)Children.Length; } } else { Children = new VariableInformation[0]; CountChildren = 0; } if (_format != null) { foreach (var child in Children) { await child.Format(); } } }