Skip to content

Unable to patch methods which DeclaringType is null #445

Description

@GeorgyPorgy

Describe the bug

When a target method is resolved via Module.ResolveMethod(int Token) its DeclaringType property is null and future attempt to patch the method triggers "System.NullReferenceException: Object reference not set to an instance of an object" at CreateDynamicMethod(MethodBase original, String suffix, Boolean debug)

In fact, the problem described is similar to that described in an already closed ticket. : "Unable to patch methods located inside the GlobalType (aka. ) #235 "

To Reproduce
Steps to reproduce the behavior:

  1. Resolve a method inside the GlobalType via Module.ResolveMethod (int Token)
  2. Apply patch to it ( Transpiler type in my case )
  3. The last line in the Harmony debug log reports : ### Patch: static System.UInt32 MethodBlaBlaBla(System.Byte* arg1, System.Byte* arg2 , System.Int32 arg3, System.SByte* arg4, SomeStruct* arg5)
  4. The target app errors log reports :
    ERROR - System.NullReferenceException: Object reference not set to an instance of an object.
    at HarmonyLib.MethodPatcher.CreateDynamicMethod(MethodBase original, String suffix, Boolean debug)
    at HarmonyLib.MethodPatcher..ctor(MethodBase original, MethodBase source, List1 prefixes, List1 postfixes, List1 transpilers, List1 finalizers, Boolean debug)
    at HarmonyLib.PatchFunctions.UpdateWrapper(MethodBase original, PatchInfo patchInfo)
    at HarmonyLib.PatchProcessor.Patch()

Expected behavior
The patch gets applied.

Runtime environment (please complete the following information):

  • OS: Windows 10, 64bit
  • .NET version 4.7.2
  • Harmony version 2.2.0.0

Activity

  1. pardeike commented on Jan 5, 2022

    @pardeike
    Owner

    Can you please verify with master that the issue is solved and reopen it if it isn't?

  2. pardeike commented on Jan 6, 2022

    @pardeike
    Owner
  3. GeorgyPorgy commented on Jan 7, 2022

    @GeorgyPorgy
    Author

    I checked the behavior with the new changes and it seems some of the problems have already been fixed, but the patching has not yet ended successfully.
    Patching work finished with following error : System.InvalidCastException: Unable to cast object of type 'ModifierType' to type 'System.Type'.

    The last line in the Harmony debug log reports :
    ### Replacement: static System.UInt32 GLOBALTYPE::GLOBALTYPE.MethodBlaBlaBla(System.Byte* arg1, ....

    while in the application log the messages list is as follows :
    ERROR - System.InvalidCastException: Unable to cast object of type 'ModifierType' to type 'System.Type'.
    at HarmonyLib.InlineSignatureParser.g__ReadTypeSignature|0_4(<>c__DisplayClass0_0& )
    at HarmonyLib.InlineSignatureParser.g__ReadMethodSignature|0_0(InlineSignature method, <>c__DisplayClass0_0& )
    at HarmonyLib.InlineSignatureParser.ImportCallSite(Module moduleFrom, Byte[] data)
    at HarmonyLib.MethodBodyReader.ReadOperand(ILInstruction instruction)
    at HarmonyLib.MethodBodyReader.ReadInstructions()
    at HarmonyLib.MethodPatcher.CreateReplacement(Dictionary`2& finalInstructions)
    at HarmonyLib.PatchFunctions.UpdateWrapper(MethodBase original, PatchInfo patchInfo)
    at HarmonyLib.PatchProcessor.Patch()

    Runtime environment :

    • OS: Windows 10, 64bit
      
    • .NET version 4.7.2
      
    • Harmony version 2.2.0.0-master branch
      
  4. pardeike commented on Jan 7, 2022

    @pardeike
    Owner

    Right now, I can only guess the problem because I have no idea how to write a test for such a method. If you know a way to reference such a method in a test please let me know.

  5. pardeike commented on Jan 7, 2022

    @pardeike
    Owner

    Also the stacktrace indicates that your original method has some very unusual IL codes that trigger the InlineSignature parser. Could you tell me more about your original method and maybe list it’s IL code. Parsing inline IL is still new and not much tested either and has nothing to do with the method being without type.

  6. pardeike commented on Jan 7, 2022

    @pardeike
    Owner

    On further inspection, the stacktrace isn’t helpful because there are several casts to Type that could fail so if you could be so kind to make your debugger stop at the exception and maybe give us some overview of what bytes the reader is reading, then me and @0x0ade who wrote the code can help you better.

  7. GeorgyPorgy commented on Jan 8, 2022

    @GeorgyPorgy
    Author

    Thanks for your efforts, Andreas.

    The method IL code can be seen at the link below :
    https://drive.google.com/file/d/1Jq3teFou0PC4ZW0jnGvxcAaMZopZGJYr/view?usp=sharing

    The instruction list was generated with ILSpy.

    I will attempt to extract additional information with the help of the debugger and provide it as soon as possible.

    P.S.
    I modified the function "ReadInstructions()" to log the information about the position of the currently processed instruction, but before analyzing its operand ...
    The last reported number is 0x0019, which means that the exception occurs when processing the operand in the 'calli' instruction.

  8. pardeike commented on Jan 10, 2022

    @pardeike
    Owner

    At this point it is unclear if it is at all possible to create the correct result from this calli due to my possible limitations in the c# reflection api.

    I spoke with @0x0ade and it looks like there might be a very convoluted way to support this but at this point it’s unclear if and who could implement this. It’s a rather difficult topic.

  9. GeorgyPorgy commented on Jan 13, 2022

    @GeorgyPorgy
    Author

    Hello Andreas,

    https://www.codeproject.com/Articles/1244372/Reflecting-Within-a-Method-Body
    section 'InlineSig'

    Would this article help us ?

    regards

  10. pardeike commented on Jan 13, 2022

    @pardeike
    Owner

    That article just shows the basics. Our code here handles this case already:

    case OperandType.InlineSig:

    It’s the parser that fails the case because it is more complicated than the article suggests.

  11. added a commit that references this issue on Feb 1, 2024
    220ef9e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions