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(); }
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); }
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!"); } } }
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!"); } }
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); }
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(); }
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); } }
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; }
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); }