Example #1
0
        void FixBody(MethodBody body, TypeDefinition localDesigner)
        {
            Dictionary <Instruction, int> instructions = new Dictionary <Instruction, int>();
            var    processor        = body.GetILProcessor();
            string designerFullName = $"{localDesigner.FullName}/";

            foreach (var i in body.Instructions)
            {
                string line = i.ToString();
                if (line.Contains(designerFullName) && !instructions.ContainsKey(i))
                {
                    var match = opCodeRegex.Match(line);
                    if (match.Success && match.Groups.Count == 5)
                    {
                        string key = match.Groups[4].Value.Replace(designerFullName, string.Empty);
                        if (designerConstants.ContainsKey(key) && !instructions.ContainsKey(i))
                        {
                            instructions.Add(i, designerConstants [key]);
                        }
                    }
                }
            }
            if (instructions.Count > 0)
            {
                Context.LogMessage($"    Fixing up {body.Method.FullName}");
            }
            foreach (var i in instructions)
            {
                var newCode = Extensions.CreateLoadArraySizeOrOffsetInstruction(i.Value);
                Context.LogMessage($"      Replacing {i.Key}");
                Context.LogMessage($"      With {newCode}");
                processor.Replace(i.Key, newCode);
            }
        }
Example #2
0
        void UpdateMagicPrefill(TypeDefinition magicType)
        {
            var fieldTypesMap = magicType.Fields.FirstOrDefault(f => f.Name == "typesMap");

            if (fieldTypesMap == null)
            {
                return;
            }

            var methodPrefill = Extensions.GetMethod(magicType, "Prefill");

            if (methodPrefill == null)
            {
                return;
            }

            var typeDictionary        = _context.GetType("mscorlib", "System.Collections.Generic.Dictionary`2");
            var ctorDictionary        = Extensions.GetMethod(typeDictionary, ".ctor", new string[] { "System.Int32" });
            var methodSetItem         = Extensions.GetMethod(typeDictionary, "set_Item", new string[] { "TKey", "TValue" });
            var genericTypeDictionary = new GenericInstanceType(typeDictionary);

            genericTypeDictionary.GenericArguments.Add(_context.GetType("mscorlib", "System.String"));
            genericTypeDictionary.GenericArguments.Add(_context.GetType("mscorlib", "System.Int32"));

            var genericMethodDictionaryCtor    = CreateGenericMethodReference(ctorDictionary, genericTypeDictionary);
            var genericMethodDictionarySetItem = CreateGenericMethodReference(methodSetItem, genericTypeDictionary);
            var importedMethodSetItem          = magicType.Module.ImportReference(genericMethodDictionarySetItem);

            var instructions = methodPrefill.Body.Instructions;

            instructions.Clear();

            instructions.Add(Extensions.CreateLoadArraySizeOrOffsetInstruction(marshalTypes.Count));
            instructions.Add(Instruction.Create(OpCodes.Newobj, magicType.Module.ImportReference(genericMethodDictionaryCtor)));
            instructions.Add(Instruction.Create(OpCodes.Stsfld, fieldTypesMap));

            int idx = 0;

            foreach (var type in marshalTypes)
            {
                instructions.Add(Instruction.Create(OpCodes.Ldsfld, fieldTypesMap));
                instructions.Add(Instruction.Create(OpCodes.Ldstr, type.FullName.Replace("/__<$>_jni_marshal_methods", "").Replace("/", "+")));
                instructions.Add(Extensions.CreateLoadArraySizeOrOffsetInstruction(idx++));
                instructions.Add(Instruction.Create(OpCodes.Callvirt, importedMethodSetItem));
            }

            instructions.Add(Instruction.Create(OpCodes.Ret));
        }
Example #3
0
        bool UpdateMarshalRegisterMethod(MethodDefinition method, HashSet <string> markedMethods)
        {
            var instructions     = method.Body.Instructions;
            var arraySizeUpdated = false;
            var idx         = 0;
            var arrayOffset = 0;

            while (idx < instructions.Count)
            {
                if (!arraySizeUpdated && idx + 1 < instructions.Count)
                {
                    int length;
                    if (IsLdcI4(instructions [idx++], out length) && instructions [idx].OpCode == OpCodes.Newarr)
                    {
                        instructions [idx - 1] = Extensions.CreateLoadArraySizeOrOffsetInstruction(markedMethods.Count);
                        idx++;
                        arraySizeUpdated = true;
                        continue;
                    }
                }
                else if (idx + 9 < instructions.Count)
                {
                    var chunkStart = idx;
                    if (instructions [idx++].OpCode != OpCodes.Dup)
                    {
                        continue;
                    }

                    int offset;
                    var offsetIdx = idx;
                    if (!IsLdcI4(instructions [idx++], out offset))
                    {
                        continue;
                    }

                    if (instructions [idx++].OpCode != OpCodes.Ldstr)
                    {
                        continue;
                    }

                    if (instructions [idx++].OpCode != OpCodes.Ldstr)
                    {
                        continue;
                    }

                    if (instructions [idx++].OpCode != OpCodes.Ldnull)
                    {
                        continue;
                    }

                    if (instructions [idx++].OpCode != OpCodes.Ldftn)
                    {
                        continue;
                    }

                    if (!(instructions [idx - 1].Operand is MethodReference mr))
                    {
                        continue;
                    }

                    if (instructions [idx++].OpCode != OpCodes.Newobj)
                    {
                        continue;
                    }

                    if (instructions [idx++].OpCode != OpCodes.Newobj)
                    {
                        continue;
                    }

                    var chunkEnd = idx;
                    if (instructions [idx++].OpCode != OpCodes.Stelem_Any)
                    {
                        continue;
                    }

                    if (markedMethods.Contains(mr.Name))
                    {
                        instructions [offsetIdx] = Extensions.CreateLoadArraySizeOrOffsetInstruction(arrayOffset++);
                        continue;
                    }

                    for (int i = 0; i <= chunkEnd - chunkStart; i++)
                    {
                        instructions.RemoveAt(chunkStart);
                    }

                    idx = chunkStart;
                }
                else
                {
                    break;
                }
            }

            if (!arraySizeUpdated || arrayOffset != markedMethods.Count)
            {
                _context.LogMessage($"Unable to update {method} size updated {arraySizeUpdated} counts {arrayOffset} {markedMethods.Count}");
                return(false);
            }

            MarkMethod(method);

            return(true);
        }