Click here to Skip to main content
15,886,110 members
Articles / Programming Languages / C#
Article

Inside the .NET Application

Rate me:
Please Sign up or sign in to vote.
3.49/5 (27 votes)
12 Jan 20046 min read 58.6K   23   2
This article provides low level discussion about the PE file structure.

Introduction

I hope everyone has heard and tried the new .NET technology by now. And we have started loving all those cool features in .NET, we’ve been dreaming for long time. So in this article, I’m going to drill in to the detail level of the PE (Portable Executable file) structure and what are the primary differences made out to make .NET so interesting.

The PE File Structure

Well, I think a simple Hello World program I wrote in C# when the .NET beta 1 was released would be enough for this. So here, I present my code in figure 01.

Sample screenshot

Figure 01

It does nothing than printing “Hello C# world” in the console window. Well, when you compile and build this, you will have a binary image. In my case, it is “HelloWorld.exe”. This is a Microsoft COFF (Common Object File Format) PE (Portable Executable) file. Now, we are going to see what’s inside this PE file. Actually I can say, in a .NET compatible PE file, there are 3 sections.

The first one, we call the PE header. This section has the information about the contents of the rest of the file. Basically, you can think of it as an index. Also, it defines the RVA of the one and only entry point to the executable code.

Ok, let me show you some interesting stuff. If you are a C++ fan like me, you should be able to get the dump image of this file using a dump tool. Ok, in figure2, I have shown a part of the first header, I got from the dump.

Sample screenshot

Figure 02

Well, if you are familiar with Win32 days dumps, you don’t see a big difference between the 2 dumps. But take a look at the last 2 rows in this list. Earlier it was reserved placeholder and did not hold any RVA. But now it’s replaced by the entry “COM descriptor directory”. This is the place the .NET runtime recognizes this file as a managed executable. This RVA points to the location of the metadata. I’ll talk about metadata very soon. Until then, I have few more things to show you in my dump. If we go down a little further, we can see the section shown in figure 3.

Sample screenshot

Figure 03

In that you can see, it has the location of the PDB file, which will be used for debugging. You will see this only if you compile the program with the debug setting. Then right after that, there are four letters BSJB. It’s always BSJB. So what is this? This is the first entry in the metadata table. If you convert it to a hexadecimal value, it will turn out to be 0X42534A42. So this is a combination of the first 4 letters of the names of the 4 guys who worked on metadata engine. Then next to that, you can see the runtime version of .NET supported by the PE file. In my case, it’s framework 1.0.3705. Following the version, it has the names and addresses of the heap data structures. A PE file contains 4 heap data structures named String, User String, GUID and Blob. I will tell what the heap data structures are, in the next few paragraphs.

I only got one more thing to show you in my dump. Look at figure 04.

Sample screenshot

Figure 04

This section is called CLR header. And this will be examined by the common language runtime to obtain the RVA of the metadata directory. There is a simple logic to obtain the offset to the table out of the RVA shown there. In my program, it’s 20DC. But explaining it is not in the scope of this article. So I’ll leave it to the next one. Also, this section contains the entry point token to the executable code. Here it is 6000001.

The following section to the above is also a bit interesting. There we have said that there is link to another module mscoree.dll. That is the core of common language runtime. It also specifies the entry point to the mscoree.dll, which allows the module to be attached to the current process. Here it’s shown as 0 _CorExeMain.

So that’s a little about the PE header. Next one is the Metadata section. When .NET compiles a program, it does not compile it to native code. Rather it compiles to an intermediate language (MSIL). The metadata describes the objects. Metadata contains a set of tables that contain the description of types available in the PE and their behaviors. For example, there is one table to hold the classes and there is another to hold the methods supported by those classes. Each table and rows in the tables have identifiers. And one more thing I should mention is that Metadata does not store the user readable names of the classes, methods, custom types and so on. Instead, it uses the heap data structures I mentioned above to store them. And the tables have references to those values in the heap data structures. For example, if I have a method called foo() in my code. The metadata table, which contains the methods, would not store the name foo in it. It stores the reference in the heap data structure (in this case it is String Heap Data Structure). I think now you have the answer that you’ve been looking for a long time. Why no IDL in .NET? The answer is simply because of the metadata the PE files are said to be self-describing components. That’s how .NET achieves features as cross language compatibility, xCopy deployment, Easy component Versioning and so on.

We have looked at PE header and metadata. But still the most important part for me is missing. That is my code. Well actually the section 3 contains my code compiled to IL assembler. This MSIL code is stored along with the metadata tokens. A metadata token is a four-byte number. The top byte denotes the metadata table to which a particular token refers (method, type, and so on). The remaining three bytes specify the row in the metadata table that corresponds to the programming element being described. If you define a method in C# and compile it into a PE file, the following metadata token might exist in the MSIL portion of the PE file:

0x06000004

The top byte (0x06) indicates that this is a MethodDef token. The lower three bytes (000004) tell the common language runtime to look in the fourth row of the MethodDef table for the information that describes this method definition. So when a function is called in a PE file, it finds the corresponding location of the MSIL code using the metadata tokens and compiles it using the JIT compiler. When it comes to compiling, .NET thinks that some functions will not be called during the program execution. So it compiles the MSIL on demand which in turn gives you the best experience in program execution.

So that’s about the inside of the PE file structure and how it interacts with the program execution.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Sri Lanka Sri Lanka
Software engineer, Researcher.

Comments and Discussions

 
GeneralInside the .NET Application Pin
sendtosharad18-Aug-06 5:16
sendtosharad18-Aug-06 5:16 
GeneralSmokin'! Pin
IgDev19-Jan-04 17:02
IgDev19-Jan-04 17:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.