Example #1
0
        internal DllField(FieldDefinition f)
        {
            LayoutOffset  = f.Offset;
            DeclaringType = DllTypeRef.From(f.DeclaringType);
            Type          = DllTypeRef.From(f.FieldType);
            Name          = f.Name;
            Offset        = -1;
            if (f.HasCustomAttributes)
            {
                foreach (var ca in f.CustomAttributes)
                {
                    if (ca.AttributeType.Name == "FieldOffsetAttribute")
                    {
                        if (ca.Fields.Count > 0)
                        {
                            Offset = Convert.ToInt32(ca.Fields.FirstOrDefault().Argument.Value as string, 16);
                        }
                    }
                    else
                    {
                        // Ignore the DummyDll attributes
                        var atr = new DllAttribute(ca);
                        if (!string.IsNullOrEmpty(atr.Name))
                        {
                            Attributes.Add(atr);
                        }
                    }
                }
            }

            Specifiers.AddRange(DllSpecifierHelpers.From(f));

            This     = f;
            Constant = f.Constant;
        }
        internal DllField(FieldDefinition f, TypeDefinition info)
        {
            LayoutOffset  = f.Offset;
            DeclaringType = DllTypeRef.From(f.DeclaringType);
            Type          = DllTypeRef.From(f.FieldType);
            Name          = f.Name;
            Offset        = -1;
            if (f.HasCustomAttributes)
            {
                foreach (var ca in f.CustomAttributes)
                {
                    if (ca.AttributeType.Name == "FieldOffsetAttribute" || ca.AttributeType.Name == "StaticFieldOffsetAttribute")
                    {
                        if (ca.Fields.Count > 0)
                        {
                            Offset = Convert.ToInt32(ca.Fields.FirstOrDefault().Argument.Value as string, 16);
                        }
                        //if (info.IsEnum)
                        //    // Because Il2CppInspector is bad and emits 0x10 for fields on enums. I seriously don't know why.
                        //    Offset -= 0x10;
                    }
                    else
                    {
                        // Ignore the DummyDll attributes
                        var atr = new DllAttribute(ca);
                        if (!string.IsNullOrEmpty(atr.Name))
                        {
                            Attributes.Add(atr);
                        }
                    }
                }
            }

            Specifiers.AddRange(DllSpecifierHelpers.From(f));

            This     = f;
            Constant = f.Constant;
        }
Example #3
0
        private DllMethod(MethodDefinition m, ref HashSet <MethodDefinition> mappedBaseMethods)
        {
            cache.Add(m, this);
            This = m;
            // Il2CppName is the MethodDefinition Name (hopefully we don't need to convert it for il2cpp, but we might)
            Il2CppName = m.Name;
            // F**k you parens
            Name = m.Name.Replace('(', '_').Replace(')', '_');
            Parameters.AddRange(m.Parameters.Select(p => new Parameter(p)));
            Specifiers.AddRange(DllSpecifierHelpers.From(m));
            // This is not necessary: m.GenericParameters.Any(param => !m.DeclaringType.GenericParameters.Contains(param));
            Generic           = m.HasGenericParameters;
            GenericParameters = m.GenericParameters.Select(g => DllTypeRef.From(g)).ToList();

            // This may not always be the case, we could have a special name in which case we have to do some sorcery
            // Grab the special name, grab the type from the special name
            // This only applies to methods that are not new slot
            if (!m.IsNewSlot)
            {
                int idxDot = Name.LastIndexOf('.');
                if (idxDot >= 2 && !Name.StartsWith("<"))
                {
                    // Call a utilities function for converting a special name method to a proper base method
                    var baseMethod = m.GetSpecialNameBaseMethod(out var iface, idxDot);
                    if (baseMethod is null)
                    {
                        throw new Exception("Failed to find baseMethod for dotted method name!");
                    }
                    if (iface is null)
                    {
                        throw new Exception("Failed to get iface for dotted method name!");
                    }
                    if (!mappedBaseMethods.Add(baseMethod))
                    {
                        throw new InvalidOperationException($"Base method: {baseMethod} has already been overriden!");
                    }
                    // Only one base method for special named methods
                    BaseMethods.Add(From(baseMethod, ref mappedBaseMethods));
                    ImplementedFrom = DllTypeRef.From(iface);
                    IsSpecialName   = true;
                }
                else
                {
                    var baseMethod = m.GetBaseMethod();
                    if (baseMethod == m)
                    {
                        var baseMethods = m.GetBaseMethods();
                        if (baseMethods.Count > 0)
                        {
                            HidesBase = true;
                        }
                        // We need to check here SPECIFICALLY for a method in our declaring type that shares the same name as us, since we could have the same BaseMethod as it.
                        // If either ourselves or a method of the same safe name (after . prefixes) exists, we need to ensure that only the one with the dots gets the base method
                        // It correctly describes.
                        // Basically, we need to take all our specially named methods on our type that have already been defined and remove them from our current list of baseMethods.
                        // We should only ever have baseMethods of methods that are of methods that we haven't already used yet.
                        if (baseMethods.Count > 0)
                        {
                            foreach (var baseM in mappedBaseMethods)
                            {
                                baseMethods.Remove(baseM);
                            }
                        }
                        foreach (var bm in baseMethods)
                        {
                            BaseMethods.Add(From(bm, ref mappedBaseMethods));
                        }
                    }
                    else
                    {
                        if (!mappedBaseMethods.Add(baseMethod))
                        {
                            throw new InvalidOperationException($"Base method: {baseMethod} has already been overriden!");
                        }
                        BaseMethods.Add(From(baseMethod, ref mappedBaseMethods));
                    }
                }
            }
            if (BaseMethods.Count > 0)
            {
                // TODO: This may not be true for generic methods. Should ensure validity for IEnumerator<T> methods
                // This method is an implemented/overriden method.
                // TODO: We need to double check to see if we need multiple ImplementedFroms
                ImplementedFrom = BaseMethods.First().DeclaringType;
                // Add ourselves to our BaseMethod's ImplementingMethods
                foreach (var bm in BaseMethods)
                {
                    bm.ImplementingMethods.Add(this);
                }
            }

            ReturnType    = DllTypeRef.From(m.ReturnType);
            DeclaringType = DllTypeRef.From(m.DeclaringType);
            // This is a very rare condition that we need to handle if it ever happens, but for now just log it
            if (m.HasOverrides)
            {
                Console.WriteLine($"{m}.HasOverrides!!! Overrides: {string.Join(", ", m.Overrides)}");
            }

            IsVirtual = m.IsVirtual || m.IsAbstract;

            RVA    = -1;
            Offset = -1;
            VA     = -1;
            Slot   = -1;
            if (m.HasCustomAttributes)
            {
                foreach (var ca in m.CustomAttributes)
                {
                    if (ca.AttributeType.Name == "AddressAttribute")
                    {
                        if (ca.Fields.Count >= 3)
                        {
                            for (int i = 0; i < ca.Fields.Count; i++)
                            {
                                var f = ca.Fields[i];
                                if (f.Name == "RVA" || f.Name == "Offset" || f.Name == "VA")
                                {
                                    var val = Convert.ToInt32(f.Argument.Value as string, 16);
                                    if (f.Name == "RVA")
                                    {
                                        RVA = val;
                                    }
                                    else if (f.Name == "Offset")
                                    {
                                        Offset = val;
                                    }
                                    else if (f.Name == "VA")
                                    {
                                        VA = val;
                                    }
                                }
                                else if (f.Name == "Slot")
                                {
                                    Slot = Convert.ToInt32(f.Argument.Value as string);
                                }
                            }
                        }
                    }
                    else
                    {
                        var atr = new DllAttribute(ca);
                        if (!string.IsNullOrEmpty(atr.Name))
                        {
                            Attributes.Add(atr);
                        }
                    }
                }
            }
        }