PIX Managed x64

Published May 26, 2010
Advertisement
PIX is a great tool for profiling and debugging Direct3D applications. A lot of developers swear by it. There is slight problem though: the 64-bit version of PIX doesn't handle managed applications properly. When you go to launch a 64-bit managed app, it complains that it cannot start the process. We've reported the bug before, but there hasn't been much enthusiasm in seeing it fixed (understandable since MS doesn't have a 64-bit managed offering of DirectX at the moment). This can be quite annoying for users of SlimDX though (and possibly the Windows API Code Pack as well). So I set out to build a workaround.

My idea was thus: to build a native x64 application that would in turn launch the x64 managed target and ensure that PIX hooked up with it properly. It turned out to be simpler than I thought. Microsoft provides the CLR Hosting API, which lets you hook into and run managed code inside your process. To start with, I tried simply initializing the CLR, cleaning it up again, and exiting, expecting PIX to fail. Surprisingly, it did not. It makes me wonder what exactly the default CLR loader is doing differently.

Starting the CLR is easy:
ICLRRuntimeHost *host = 0;CorBindToRuntimeEx(L"v2.0.50727", L"svr", STARTUP_CONCURRENT_GC, CLSID_CLRRuntimeHost,    IID_ICLRRuntimeHost, reinterpret_cast(&host));host->Start();


Unfortunately, executing a managed program isn't so easy. The hosting API only provides one main function to launch a managed executable in-process, and the signature requirements for the target method are rather odd. Instead of accepting one of the signatures of Main() as the target, you have to provide an entry point that takes a single string parameter and returns an integer value. This of course matches none of the possible C# entry points, and I didn't want users to have to modify their programs to make them compatible with my fix.

The solution I used was to insert an additional C# DLL in between my native loader and the target application. This assembly provides the required entry point function, taking the path to the target app as the single parameter. It then runs the executable within the same appdomain, ensuring that we keep this all in a single process so as not to confus PIX:
public static int Start(string path){    return AppDomain.CurrentDomain.ExecuteAssembly(path);}


Now we can call into Start from our native loader and forward a command line argument representing the path of the target application.
DWORD ret;host->ExecuteInDefaultAppDomain(path.c_str(), L"PIXPlug.Shim.AppRunner", L"Start",    lexical_cast(argv[1]).c_str(), &ret);


Opening PIX, I provide my native launcher as the target, and pass the path to my managed application as the command line argument. Click launch and... success! The managed application launches and starts rendering. PIX hooks in and starts giving me debugging data. I've successfully tricked PIX into thinking this managed x64 application is actually running natively.
Previous Entry Quiz Answers
0 likes 1 comments

Comments

STufaro
Quote:
Click launch and... success! The managed application launches and starts rendering. PIX hooks in and starts giving me debugging data. I've successfully tricked PIX into thinking this managed x64 application is actually running natively.


So that's where this giant hole that appeared in my universe came from.
June 13, 2010 06:17 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement

Latest Entries

New Blog

2022 views

Progress Update

1550 views

Start of Project

1513 views

New Job

2220 views

The Downward Spiral

2879 views

Job Interviews

1480 views
Advertisement