Ryder icon indicating copy to clipboard operation
Ryder copied to clipboard

"methods whose bodies are too close to one another"?

Open logiclrd opened this issue 6 years ago • 6 comments

I have a project where I am patching a bug in the WPF TreeView class by replacing one of its non-public methods with my own implementation. I am installing this "shim" with the following code:

	public static void Install()
	{
		var realMethod = typeof(System.Windows.Controls.TreeView).GetMethod("HandleMouseButtonDown", BindingFlags.Instance | BindingFlags.NonPublic);
		var replacementMethod = typeof(TreeViewShim).GetMethod(nameof(TreeView_HandleMouseButtonDown_shim), BindingFlags.Static | BindingFlags.NonPublic);

		Redirection.Redirect(realMethod, replacementMethod);
	}

This has been working fine on a variety of workstations for several months, but a co-worker's machine just the other day started throwing this exception:

        if ((sizeOfPtr == sizeof(long) && difference < 13) || (sizeOfPtr == sizeof(int) && difference < 7))
            throw new InvalidOperationException("Unable to redirect methods whose bodies are too close to one another.");

https://github.com/6A/Ryder/blob/master/Ryder.Lightweight/Ryder.Lightweight.cs#L61

To get things working for now, I am going to try a bit of an ugly work-around: I will make two identical copies of my shim method, and if one of them is too close, then in theory it should be impossible for the other one to also be too close (even if it is a trampoline). But, I'm trying to understand why:

a) this works fine on many other machines,

b) it just stopped working on this particular machine where it was working before, and

c) how methods in different classes can have entrypoints less than 13 bytes apart.

What is the correct fix in this situation??

logiclrd avatar Apr 27 '18 17:04 logiclrd

Update: The work-around did not succeed. Will try to gather further information.

logiclrd avatar Apr 27 '18 17:04 logiclrd

A further update: After restarting Windows, the problem went away. The person who observed the bug is pretty sure that this happened once before, as well -- a reboot fixed it, but then it recurred.

logiclrd avatar Apr 27 '18 19:04 logiclrd

Mhm, all this is very strange. Furthermore, I've only ever observed errors due to close method bodies on methods of a same class. I'll look into it.

71 avatar Apr 28 '18 15:04 71

Do you use the lightweight version (or the full version, if you don't mind recompiling it)? If so, can you try moving these lines below those ones?

I suspect none of the methods have been jitted yet, and thus point to temporary memory locations that might be close to one another.

Alternatively, you can try invoking your TreeView_HandleMouseButtonDown_shim method before creating the redirection, which will force its compilation (you can provide invalid arguments and make it throw, that's fine).

71 avatar Apr 28 '18 15:04 71

I will try all those things if/when the problem recurs. As of right now, rebooting the system apparently fixed it, but my coworker will definitely reach out to me if it starts happening again. I also made a test application for him to run that fully annotates all values and the logic flow within the Redirection.Redirect method, so we're well equipped for when we see the problem again.

logiclrd avatar Apr 30 '18 15:04 logiclrd

Okay, so hopefully we get to the bottom of this. But this kind of behavior makes me wonder how exactly I have control over it...

71 avatar Apr 30 '18 20:04 71