Recently I had to debug Google's Storage SDK. Apparently the natural way to do it in today's OSS world is to simply clone the repo, build it locally and debug what you want. You wish! The codebase is in my opinion so convoluted and mostly autogenerated, that it's completely useless for a programmer and completely pointless to start understanding it. In addition to that, the code simply doesn't build locally. One probably has to employ some internal Google tools and scripts to do that (maybe Google developers never heard of .NET/C#?) maybe in a similar way you build Google Chrome. It also could be a pay pack for someone asking to opensource the code? This coding style is another way of encryption - yeah you can read it but it's garbage and so is useless.
The final solution to do that is employing dotPeek from Jetbrains. Most people use it for decompiling .NET assemblies and browsing source code. Hey, even the home page says what you should use it for:
And yeah, you can browse decompiled Google SDK by fetching it from NuGet, and the decompiled view of dotPeek is actually better in many ways than the one published on GitHub! :) Lately I was actually wondering why anyone needs dotPeek, when most of the code is open-source anyway, and it's so rare to see anything .NET related in binary only form. Yeah, it might be useful to hack some
.dll of a third-party's internal library, but that's not too interesting and doesn't happen often. In this particular case, one can use dotPeek to browse code, when open-source project source is so convoluted that it doesn't even compile on a clean machine.
By the way, no, you cannot use dotPeek to debug third-party code, at lease not on it's own. What you can do though, is use Visual Studio ❤ dotPeek to debug ANY third-party code.
To understand it propely, one needs to understand how Visual Studio debugs anything at all. To start simple, we are going to look at you own code. When compiled in Debug configuration, .net compiler will generate two things (more, but we're trying to be simple):
- binary (.dll, .exe etc.)
- debug symbols (.pdb) Debug symbols are actually generated in Release mode as well, but they are limited in a way that doesn't help us to debug code we've written. Maybe it's a separate discussion.
When you start the debug session, VS (or on that note, any other .NET IDE like Jetbrains Rider, VS Code etc.) will use information in the
.pdb file to look up metadata regarding what in the compiled binary corresponds to which source code (again, speaking simply). Without it you coudl still debug, but you won't be able to know what you are doing or where you are relative to the original source code. Apparently
.pdb changes every time you change the code and compile it too.
So you can debug your own code now. You can also debug .NET code itself, but not by default. Say i'll step into the following line:
Guid g = Guid.NewGuid();
Nothing is going to happen, because IDE doesn't know how to debug this - there are no
.pdb files included with IDE. However, you can relatively easily turn this on:
- Not just YOUR code. In
Tools->Options->Debugging->Generalmake sure "Just my code" is OFF:
- Turn on MS Symbol Server.
Now try to step into the line. VS will ask what you want to do (I'd choose option 1 or 2 depending on how much you want to be annoyed) and now you can step into the method!
In here you'd probably guess I'm debugging this on Windows, if you didn't already by me saying it's Visual Studio :) Because the call is forwarded to the OLE 32 subsystem.
The second option in symbol servers is "Nuget.org Symbol Server" whic hmay be of interest to you as well. This allows to download debug symbols from nuget.org and debug external code that way. However, one of the serious limitations of this approach (and the reason it didn't work for me) is that it's package dependent. Package author must publish debug symbols along with the package's binary. Which Google didn't. And we know why.
Now that you know you can debug pretty much anything, as long as you have debug symbols, we can come back to dotPeek. See, one of the cool features of dotPeek, but not very well known is that dotPeek can act as a symbol server itself, meaning you can point IDE (VS) to dotPeek and offload symbol generation task to it. As it's a decompiler, it only feels natural to server debug info from dotPeek - it already parsed and understood the binary, displayed associated source code, and made it pretty.
So what you can do next is load packages/assemblies you need into the Assembly Explorer and just the ones you want to debug. Keep in mind that generating debug symbols can be a lengthy operation, therefore I'd recommend keeping it to the minimum. This particular package probably took around 10 seconds, but if you try to debug entire .NET SDK it may take tens of minutes just to start with.
Then to to
Tools->Symbol Server to start the server. It may display some dialogs when you do that first time, but I've lost that and can't remember what it was. I think one of the options was to only generate debug symbols for Assembly Explorer opened things which I did.
Anyway there is configuration to change all that. And status bar of dotPeek displays basic information like server address and progress of generting debug symbols. Note that server will start almost instantly, and only generate stuff on request, i.e. when you step into a particular method from IDE, therefore delays are expected on first step-ins into a
And the last thing to do is to add the address of dotPeek symbol server to VS settings:
Note that when you are doing so, just add entire URL as "symbol file location" and that's it. Leave everything else as default, it's bloody not obvious when using VS UI!
Now just start the debugging session and observe normal "step in" just like it's your own!
P.S. This article was originally published on my blog.