public ArbitrageItemSorter(SField field, SortOrder order) { _sField = field; _sortOrder = order; }
public Task <Core.Type> GetTypeFromDebugger(string module, string typename) { return(this.runner.AttemptOperation <Core.Type>(() => { uint typeSize = 0; ulong moduleBase; try { moduleBase = this.symbolCache.GetModuleBase(module); } catch { throw new DebuggerException(String.Format("Invalid module name: {0}", module)); } // Get the type id. uint typeId; try { typeId = this.symbolCache.GetTypeId(moduleBase, typename); } catch { throw new DebuggerException(String.Format("Invalid type name: {0}", typename)); } // Get the type size. try { typeSize = this.symbolCache.GetTypeSize(moduleBase, typeId); } catch { throw new DebuggerException("Internal Exception: Invalid type id."); } // The type is valid so we should be able to dt it without any problems. string command = String.Format("dt -v {0}!{1}", module, typename); System.Diagnostics.Debug.WriteLine(String.Format("Executing command: {0}", command)); DumpTypeParser parser = new DumpTypeParser(); this.client.DebugOutput += parser.DumpTypeOutputHandler; this.client.DebugOutput += PrintDotOnDebugOutput; this.control.Execute(OutputControl.ToThisClient, command, ExecuteOptions.NotLogged); this.client.FlushCallbacks(); this.client.DebugOutput -= PrintDotOnDebugOutput; this.client.DebugOutput -= parser.DumpTypeOutputHandler; System.Diagnostics.Debug.WriteLine(String.Format("Done executing.", command)); parser.Parse(); if (parser.AnonymousEnums.Count > 0) { List <string> anonymousEnums = parser.AnonymousEnums; parser.AnonymousEnums = new List <string>(); parser.ClearBuffer(); foreach (string enumType in anonymousEnums) { string enumCommand = String.Format("dt -v {0}!{1}", module, enumType); System.Diagnostics.Debug.WriteLine(String.Format("Executing command: {0}", enumCommand)); this.client.DebugOutput += parser.DumpTypeOutputHandler; this.client.DebugOutput += PrintDotOnDebugOutput; this.control.Execute(OutputControl.ToThisClient, enumCommand, ExecuteOptions.NotLogged); this.client.FlushCallbacks(); this.client.DebugOutput -= PrintDotOnDebugOutput; this.client.DebugOutput -= parser.DumpTypeOutputHandler; System.Diagnostics.Debug.WriteLine(String.Format("Done executing.", enumCommand)); } parser.Parse(); } Console.Out.WriteLine(); // Sort the parsed base classes so that the furthest base classes come first. (i.e. if C : B, and B : A, we should have [A, B], where C is the type we're getting). parser.ParsedBaseClasses.Sort((a, b) => { var endOfA = a.Offset + a.TypeSize; var endOfB = b.Offset + b.TypeSize; if (endOfA != endOfB) { // Whichever base class ends first is the "further" base class. return endOfA.CompareTo(endOfB); } else { // The base classes end at the same offset. Whichever appeared second is the "further" base class. return b.Index.CompareTo(a.Index); } }); List <SBaseType> baseTypes = new List <SBaseType>(); int currentBaseClassIndex = 0; // Construct the type. Dictionary <string, SField> fields = new Dictionary <string, SField>(); foreach (DumpTypeParser.SField parsedField in parser.ParsedFields) { // Advance the current base class index if necessary. while (currentBaseClassIndex < parser.ParsedBaseClasses.Count) { // Check if we've exhausted the fields in this base type. var currentBaseClass = parser.ParsedBaseClasses[currentBaseClassIndex]; if ((parsedField.Offset + parsedField.Size) > (currentBaseClass.Offset + currentBaseClass.TypeSize)) { // This isn't perfect for at least a couple reasons: // - All constants are associated with the final type, even if they are part of the base type. // - Base types of the base types aren't known. // The only thing this base type is sufficient for is knowing which fields are associated with each type, // which fortunately is all we need it for (right now anyway). SBaseType baseType = new SBaseType(new Core.Type(module, currentBaseClass.TypeName, currentBaseClass.TypeSize, /*isEnum*/ false, fields, null, null), (int)currentBaseClass.Offset); baseTypes.Add(baseType); fields = new Dictionary <string, SField>(); ++currentBaseClassIndex; } else { // The field is in this base type. break; } } string resolvedTypeName = parsedField.TypeName; uint resolvedTypeSize = parsedField.Size; if (resolvedTypeName == null) { // We weren't able to parse the type name. Retrieve it manually. SymbolCache.SFieldTypeAndOffset fieldTypeAndOffset; try { fieldTypeAndOffset = this.symbolCache.GetFieldTypeAndOffset(moduleBase, typeId, parsedField.FieldName); if (fieldTypeAndOffset.Offset != parsedField.Offset) { // The offsets don't match...this must be a different field? throw new Exception(); } resolvedTypeName = this.symbolCache.GetTypeName(moduleBase, fieldTypeAndOffset.FieldTypeId); } catch { throw new DebuggerException(String.Format("Internal Exception: Inconsistent field name \"{0}\" when parsing type {1}!{2}", parsedField.FieldName, module, typename)); } } if (resolvedTypeSize == uint.MaxValue) { if (!TypeCache.BuiltInTypes.TryGetValue(resolvedTypeName, out resolvedTypeSize)) { try { uint fieldTypeId = this.symbolCache.GetTypeId(moduleBase, resolvedTypeName); resolvedTypeSize = this.symbolCache.GetTypeSize(moduleBase, fieldTypeId); } catch { throw new DebuggerException(String.Format("Internal Exception: Unknown type \"{0}\" found when parsing type {1}!{2}", resolvedTypeName, module, typename)); } } } SField field = new SField(parsedField.Offset, resolvedTypeSize, module, resolvedTypeName, parsedField.BitField.BitOffset, parsedField.BitField.BitLength); // A superclass can have a field with the same name as a field in the subclass. We currently use the first one. if (!fields.ContainsKey(parsedField.FieldName)) { fields.Add(parsedField.FieldName, field); } } // Finish up the base types. while (currentBaseClassIndex < parser.ParsedBaseClasses.Count) { var currentBaseClass = parser.ParsedBaseClasses[currentBaseClassIndex]; SBaseType baseType = new SBaseType(new Core.Type(module, currentBaseClass.TypeName, currentBaseClass.TypeSize, /*isEnum*/ false, fields, null, null), (int)currentBaseClass.Offset); baseTypes.Add(baseType); fields = new Dictionary <string, SField>(); ++currentBaseClassIndex; } Dictionary <string, ulong> constants = new Dictionary <string, ulong>(); foreach (SConstantResult constant in parser.ParsedConstants) { constants.Add(constant.ConstantName, constant.Value); } return new Core.Type(module, typename, typeSize, parser.IsEnum, fields, constants, baseTypes); }, String.Format("Unable to lookup type from debugger: {0}!{1}", module, typename))); }
public StudentSorder(SField field, SortOrder order) { _sField = field; _sortOrder = order; }
internal void Parse() { string[] lines = this.buffer.ToString().Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); bool isInEnum = false; bool hasSeenFirstLine = false; string thisclass = null; foreach (string line in lines) { bool isFirstLine = !hasSeenFirstLine; hasSeenFirstLine = true; string[] parts = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); // Are we still in the enum? isInEnum = (isInEnum && parts.Length == 3 && parts[1] == "="); string offsetString = parts[0]; if (offsetString[0] == '+') { // The line has an offset. uint offset = uint.Parse(offsetString.Substring(3), System.Globalization.NumberStyles.HexNumber); switch (parts[1]) { case "__BaseClass": // +0x000 __BaseClass class [typename] uint typeSize; string typename; SBitFieldDescription bitField; bool didParseType = this.ParseType(ArraySlice(parts, 2), out typeSize, out typename, out bitField); if (didParseType) { this.ParsedBaseClasses.Add(new SBaseClass() { Offset = offset, TypeName = typename, TypeSize = typeSize, Index = this.ParsedBaseClasses.Count }); } else { System.Diagnostics.Debug.WriteLine(String.Format("Unable to parse type entry: {0}", line)); } break; case "__VFN_table": // Ignore vtables. break; default: { // A field. SField field = new SField() { Offset = offset, FieldName = parts[1] }; if (parts.Length > 3 && ParseType(ArraySlice(parts, 3), out field.Size, out field.TypeName, out field.BitField)) { this.ParsedFields.Add(field); } else { System.Diagnostics.Debug.WriteLine(String.Format("Unable to parse type entry: {0}", line)); } break; } } } else if (parts[0] == "Enum") { // We're parsing an enum. isInEnum = true; if (isFirstLine) { this.IsEnum = true; } if (parts[1].IndexOf("<unnamed-enum-") == 0 && thisclass != null) { // Strip the comma off the end. this.AnonymousEnums.Add(thisclass + "::" + parts[1].Substring(0, parts[1].Length - 1)); } } else if (isInEnum) { // Parse the constant. string name = parts[0]; string number = parts[2].Substring(2).Replace("`", ""); char baseSpecifier = parts[2][1]; System.Globalization.NumberStyles style = (baseSpecifier == 'x' ? System.Globalization.NumberStyles.AllowHexSpecifier : System.Globalization.NumberStyles.None); ulong value; if (number.Length > 0 && number[0] == '-') { style = System.Globalization.NumberStyles.AllowLeadingSign; long signedValue = long.Parse(number, style); value = (ulong)signedValue; } else { value = ulong.Parse(number, style); } this.ParsedConstants.Add(new SConstantResult() { ConstantName = name, Value = value }); } else if (parts[0] == "thisclass" && parts.Length >= 3) { // Strip the comma off the end. thisclass = parts[2].Substring(0, parts[2].Length - 1); } } }