private void LoadMethod(ImportAttribute attr, MethodInfo method, Pointer <byte> addr) { var callAttr = attr as ImportCallAttribute; Conditions.NotNull(callAttr, nameof(callAttr)); var options = callAttr.CallOptions; if (options == ImportCallOptions.None) { throw Guard.ImportFail("You must specify an option"); } bool bind = options.HasFlagFast(ImportCallOptions.Bind); bool addToMap = options.HasFlagFast(ImportCallOptions.Map); if (bind && addToMap) { throw Guard.ImportFail( $"The option {ImportCallOptions.Bind} cannot be used with {ImportCallOptions.Map}"); } if (bind) { // Global.Value.Log.Warning("Binding {Name}", method.Name); FunctionTools.SetEntryPoint(method, addr); } if (addToMap) { var enclosing = method.DeclaringType; if (enclosing == null) { throw Guard.AmbiguousFail(); } var name = method.Name; if (name.StartsWith(GET_PROPERTY_PREFIX)) { // The nameof operator does not return the name with the get prefix name = name.Erase(GET_PROPERTY_PREFIX); } m_typeImportMaps[enclosing].Add(name, addr); } }
private void Update() { _map.Clear(); if (Function == null) { return; } var args = FunctionTools.GetArguments(Function); if (args.Count() > 0) { foreach (var arg in args) { _map.Add(arg, new ModifierDependency { Name = arg }); } } }
/// <summary> /// Root unload function. Unloads and restores the type <paramref name="type"/>. /// </summary> public void Unload(Type type) { if (!IsBound(type)) { return; } if (UsingMap(type, out var mapField)) { UnloadMap(type, mapField); // Global.Value.Log.Verbose("Unloaded map in {Name}", type.Name); } (MemberInfo[] members, ImportAttribute[] attributes) = type.GetAnnotated <ImportAttribute>(); int lim = attributes.Length; for (int i = 0; i < lim; i++) { var mem = members[i]; var attr = attributes[i]; bool wasBound = attr is ImportCallAttribute callAttr && callAttr.CallOptions.HasFlagFast(ImportCallOptions.Bind); switch (mem.MemberType) { case MemberTypes.Property: var propInfo = (PropertyInfo)mem; var get = propInfo.GetMethod; // Calling the function will now result in an access violation if (wasBound) { FunctionTools.Restore(get); } break; case MemberTypes.Field: // The field will be deleted later var fi = (FieldInfo)mem; if (fi.IsStatic) { fi.SetValue(null, default); } break; case MemberTypes.Method: // Calling the function will now result in an access violation if (wasBound) { FunctionTools.Restore((MethodInfo)mem); } break; default: throw new ArgumentOutOfRangeException(); } // Global.Value.Log.Verbose("Unloaded member {Name}", mem.Name); } m_boundTypes.Remove(type); Global.Value.WriteVerbose(CONTEXT, "Unloaded {Name}", type.Name); }