示例#1
0
 public ArbitrageItemSorter(SField field, SortOrder order)
 {
     _sField    = field;
     _sortOrder = order;
 }
示例#2
0
        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)));
        }
示例#3
0
 public StudentSorder(SField field, SortOrder order)
 {
     _sField = field; _sortOrder = order;
 }
示例#4
0
        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);
                }
            }
        }