예제 #1
0
        private void WriteMessage(IRClass c, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, c.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}message {1} {{", prefix, c.ShortName);
            // Write all private types first!
            WritePrivateTypesToFile(c, w, prefix + "\t");

            // Write all fields last!
            foreach (IRClassProperty prop in c.Properties.OrderBy(prop => prop.Options.PropertyOrder))
            {
                IRClassProperty.ILPropertyOptions opts = prop.Options;
                string label = ProtoHelper.FieldLabelToString(opts.Label, false);
                string type  = ProtoHelper.TypeTostring(prop.Type, c, prop.ReferencedType);
                string tag   = opts.PropertyOrder.ToString();

                string defaultValue = "";
                if (prop.Options.DefaultValue != null)
                {
                    string formattedValue = ProtoHelper.DefaultValueToString(prop.Options.DefaultValue,
                                                                             prop.ReferencedType);
                    defaultValue = String.Format("[default = {0}]", formattedValue);
                }

                // Proto2 has repeated fields NOT PACKED by default, if they are
                // we mark that explicitly.
                string packed = "";
                if (opts.IsPacked == true && opts.Label == FieldLabel.REPEATED)
                {
                    packed = "[packed=true]";
                }

                string propName = prop.Name.PascalToSnake();
                if (packed.Length > 0 || defaultValue.Length > 0)
                {
                    tag = tag.SuffixAlign();
                }

                if (packed.Length > 0)
                {
                    defaultValue = defaultValue.SuffixAlign();
                }

                w.WriteLine("{0}{1}{2}{3} = {4}{5}{6};", prefix + "\t",
                            label.SuffixAlign(), type.SuffixAlign(), propName,
                            tag, defaultValue, packed);
            }

            // End message.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }
예제 #2
0
        private void DecompileClass_Google(IRClass target, out List <TypeDefinition> references)
        {
            // Fetch properties of the type..
            var props = GoogleCSInspector.ExtractClassProperties(_subject, out references);

            // Store properties.
            target.Properties = props;

            // Container of all parsed tags.
            List <ulong> tags = new List <ulong>();
            var          constructEnumeration = _subject.Methods.Where(GoogleCSInspector.MatchStaticConstructor);

            if (!constructEnumeration.Any())
            {
                throw new ExtractionException("No static constructor found!");
            }
            var construct = constructEnumeration.First();
            Action <CallInfo, List <byte> > cctorOnCall = (CallInfo c, List <byte> w) =>
            {
                GoogleCSInspector.StaticCctorOnCall(c, props, tags);
            };
            Action <StoreInfo, List <byte> > cctorOnStore = (StoreInfo s, List <byte> w) =>
            {
                GoogleCSInspector.StaticCctorOnStore(s, props, tags);
            };

            // Walk static constructor method.
            MethodWalker.WalkMethod(construct, cctorOnCall, cctorOnStore);

            // Extract necesary methods for decompilation.
            var serializeEnumeration = _subject.Methods.Where(GoogleCSInspector.MatchSerializeMethod);

            if (!serializeEnumeration.Any())
            {
                throw new ExtractionException("No serialize method found!");
            }

            // Get serialize method.
            var serialize = serializeEnumeration.First();

            // Handler for serialize oncall action.
            Action <CallInfo, List <byte> > googleSerializeOnCall = (CallInfo info, List <byte> w) =>
            {
                // Just chain the call.
                GoogleCSInspector.SerializeOnCall(info, w, props);
            };

            // Walk serialize method.
            MethodWalker.WalkMethod(serialize, googleSerializeOnCall, null);
        }
예제 #3
0
        public override void Decompile(out List <TypeDefinition> references)
        {
            // Create a new IRType to be filled in.
            if (IsEnum)
            {
                _constructedSubject = new IREnum(_subject.FullName, _subject.Name)
                {
                    Properties = new List <IREnumProperty>(),
                };
                // Extract the properties from this enum, local function.
                ExtractEnumProperties();

                // Enums have no references to other types.
                references = new List <TypeDefinition>();
            }
            else
            {
                var irClass = new IRClass(_subject.FullName, _subject.Name)
                {
                    PrivateTypes = new List <IRTypeNode>(),
                    Properties   = new List <IRClassProperty>(),
                };
                _constructedSubject = irClass;

                // Test for SilentOrbit decompilation.
                if (SilentOrbitInspector.MatchDecompilableClasses(_subject))
                {
                    DecompileClass_SilentOrbit(irClass, out references);
                }
                // Test for Google Protobuffer V1 decompilation.
                else if (GoogleV1Inspector.MatchDecompilableClasses(_subject))
                {
                    DecompileClass_GoogleV1(irClass, out references);
                }
                // Test for Google Protobuffer decompilation.
                else if (GoogleCSInspector.MatchDecompilableClasses(_subject))
                {
                    DecompileClass_Google(irClass, out references);
                }
                // Else fail..
                else
                {
                    throw new ExtractionException("Unrecognized proto compiler!");
                }
            }
        }
예제 #4
0
        public static string TypeTostring(PropertyTypeKind type, IRClass current,
                                          IRTypeNode reference)
        {
            switch (type)
            {
            case PropertyTypeKind.DOUBLE:
                return("double");

            case PropertyTypeKind.FLOAT:
                return("float");

            case PropertyTypeKind.INT32:
                return("int32");

            case PropertyTypeKind.INT64:
                return("int64");

            case PropertyTypeKind.UINT32:
                return("uint32");

            case PropertyTypeKind.UINT64:
                return("uint64");

            case PropertyTypeKind.FIXED32:
                return("fixed32");

            case PropertyTypeKind.FIXED64:
                return("fixed64");

            case PropertyTypeKind.BOOL:
                return("bool");

            case PropertyTypeKind.STRING:
                return("string");

            case PropertyTypeKind.BYTES:
                return("bytes");

            case PropertyTypeKind.TYPE_REF:
                return(ResolveTypeReferenceString(current, reference));

            default:
                throw new Exception("Type not recognized!");
            }
        }
예제 #5
0
        private void DecompileClass_SilentOrbit(IRClass target, out List <TypeDefinition> references)
        {
            // Fetch the properties of the type...
            // (At the same time, all references of this class are being collected.)
            var props = SilentOrbitInspector.ExtractClassProperties(_subject, out references);

            // and store the properties.
            target.Properties = props;

            // Extract necessary methods for decompilation
            var serializeEnum   = _subject.Methods.Where(SilentOrbitInspector.MatchSerializeMethod);
            var deserializeEnum = _subject.Methods.Where(SilentOrbitInspector.MatchDeserializeMethod);

            if (!serializeEnum.Any() || !deserializeEnum.Any())
            {
                throw new ExtractionException("No serialize or deserialize methods found!");
            }
            MethodDefinition serialize   = serializeEnum.First();
            MethodDefinition deserialize = deserializeEnum.First();

            // Create a handler for the serialize OnCall action.
            Action <CallInfo, List <byte> > silentOrbitSerializeCallHandler = (CallInfo info,
                                                                               List <byte> w) =>
            {
                // Just chain the call.
                // Property information is updated in place!
                SilentOrbitInspector.SerializeOnCall(info, w, props);
            };

            // Walk the serialize method for additional information.
            MethodWalker.WalkMethod(serialize, silentOrbitSerializeCallHandler, null);

            // Create handler for deserialize oncall action.
            Action <CallInfo, List <byte> > silentOrbitDeserializeCallHandler = (CallInfo info,
                                                                                 List <byte> w) =>
            {
                // Just chain the call.
                // Property information is updated in place!
                SilentOrbitInspector.DeserializeOnCall(info, w, props);
            };

            // Walk the deserialize method for additional information.
            MethodWalker.WalkMethod(deserialize, silentOrbitDeserializeCallHandler, null);
        }
예제 #6
0
        private void WriteMessage(IRClass c, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, c.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}message {1} {{", prefix, c.ShortName);
            // Write all private types first!
            WritePrivateTypesToFile(c, w, prefix + "\t");

            // Write all fields last!
            foreach (IRClassProperty prop in c.Properties.OrderBy(prop => prop.Options.PropertyOrder))
            {
                IRClassProperty.ILPropertyOptions opts = prop.Options;
                // Proto3 syntax has implicit default values!

                string label = ProtoHelper.FieldLabelToString(opts.Label, true);
                string type  = ProtoHelper.TypeTostring(prop.Type, c, prop.ReferencedType);
                string tag   = opts.PropertyOrder.ToString();

                // In proto3, the default for a repeated field is PACKED=TRUE.
                // Only if it's not packed.. we set it to false.
                string packed = "";
                if (opts.IsPacked == false && opts.Label == FieldLabel.REPEATED)
                {
                    packed = "[packed=false]";
                }

                string propName = prop.Name.PascalToSnake();
                if (packed.Length > 0)
                {
                    tag = tag.SuffixAlign();
                }

                w.WriteLine("{0}{1}{2}{3} = {4}{5};", prefix + "\t",
                            label.SuffixAlign(), type.SuffixAlign(), propName,
                            tag, packed);
            }

            // End message.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }
예제 #7
0
        private void WritePrivateTypesToFile(IRClass cl, TextWriter w, string prefix)
        {
            // Select enums and classes seperately.
            var enumEnumeration  = cl.PrivateTypes.Where(x => x is IREnum).Cast <IREnum>();
            var classEnumeration = cl.PrivateTypes.Where(x => x is IRClass).Cast <IRClass>();

            // Write out each private enum first..
            foreach (var privEnum in enumEnumeration.OrderBy(e => e.ShortName))
            {
                WriteEnum(privEnum, w, prefix);
            }

            // Then all private classes.
            foreach (var privClass in classEnumeration.OrderBy(c => c.ShortName))
            {
                // This recursively writes the private types of this class (if any).
                WriteMessage(privClass, w, prefix);
            }
        }
예제 #8
0
        private void DecompileClass_GoogleV1(IRClass target, out List <TypeDefinition> references)
        {
            // Setup containers
            var fieldNames       = new List <string>();
            var targetProperties = new List <IRClassProperty>();
            var allFields        = GoogleV1Inspector.ExtractClassFields(_subject);

            // .. and store the resulting properties into the target class.
            target.Properties = targetProperties;

            // Extract direct fields from the static data of the class.
            var staticConstructor = _subject.Methods.First(GoogleV1Inspector.MatchStaticConstructor);
            Action <CallInfo, List <byte> > cctorOnCall = (CallInfo c, List <byte> w) =>
            {
                GoogleV1Inspector.StaticCctorOnCall(c);
            };
            Action <StoreInfo, List <byte> > cctorOnStore = (StoreInfo s, List <byte> w) =>
            {
                GoogleV1Inspector.StaticCctorOnStore(s, fieldNames);
            };

            // Walk static constructor method.
            MethodWalker.WalkMethod(staticConstructor, cctorOnCall, cctorOnStore);

            // Extract direct fields from the serialize method of the class.
            var serializer      = _subject.Methods.First(GoogleV1Inspector.MatchSerializeMethod);
            var localReferences = new List <TypeDefinition>();
            Action <CallInfo, List <byte> > serializeOnCall = (CallInfo c, List <byte> w) =>
            {
                GoogleV1Inspector.SerializeOnCall(c, fieldNames, allFields, targetProperties, localReferences);
            };
            Action <StoreInfo, List <byte> > serializeOnStore = (StoreInfo s, List <byte> w) =>
            {
                GoogleV1Inspector.SerializeOnStore(s);
            };

            // Walk static constructor method.
            MethodWalker.WalkMethod(serializer, serializeOnCall, serializeOnStore);


            references = localReferences;
        }
예제 #9
0
        public static string ResolveTypeReferenceString(IRClass current, IRTypeNode reference)
        {
            var returnValue = "";
            List <IRProgramNode> currentTypeChain;            // We are not interested in this one.
            List <IRProgramNode> referenceTypeChain;

            // Check the parent namespace of both types.
            var curNS = GetNamespaceForType(current, out currentTypeChain);
            var refNS = GetNamespaceForType(reference, out referenceTypeChain);

            // Remove the namespace element so it does not interfere with dynamic string building.
            referenceTypeChain.RemoveAt(0);

            // If the namespaces match, a reference to another namespace (=package) must not be made.
            if (curNS != refNS)
            {
                // Update returnValue with the full package name of the namespace.
                returnValue += ResolvePackageName(refNS) + ".";
            }

            // If current type occurs within the referenceType chain, update the chain
            // so it references relative to that type.
            if (referenceTypeChain.Contains(current))
            {
                var removeIdx = referenceTypeChain.IndexOf(current);
                referenceTypeChain.RemoveRange(0, removeIdx + 1);
            }

            // Dynamically construct a path to the referenced type.
            // The chain does NOT include the referenced type itself!
            foreach (var type in referenceTypeChain)
            {
                returnValue += type.ShortName + ".";
            }
            // Finish with the name of the referenced type itself.
            return(returnValue + reference.ShortName);
        }