Symbian Executable File Format(转)

最近做了些涉及symbian底层的东西,找了些这方面的资料,但是symbian在这方面的文档出奇的少,很多内容都没有公布,希望symbian的开源步伐能快点啊

http://www.newlc.com/Symbian-Executable-File-Format.html

Symbian Executable File Format

in
Keywords:

This article explains the Symbian (E32) executable file format, including the header information and how the executable sections are organized. Note that this article is not based on the official specification from Symbian. They don't release the E32 specification file format and there is not so much information about it. Fortunately Symbian has released the source code of PETRAN that helps us to figure out E32 file format.

Before we start, note that here we are talking about executable file for the target (ARM), not for the emulator. Why? Because the emulator's executable files are actually using Windows PE-COFF (Portable Executable Common Object File Format). See the links at the end of this article to find out more about PE-COFF. If you don't have any knowledge about any executable file format, these links will help give you a better understanding about E32 file format later on.

Overview

The executable files in Symbian, like .app, .exe or .dll, use a special format, called E32 file format. It is a little bit different with Microsoft/Intel's PE (Portable Executable) or UNIX's ELF (Executable and Linking Format), but basically they have some similarities. You might notice that actually Symbian uses GCC compiler, it means your source code is actually compiled to PE format. Why do we have E32 then? The answer is simple, because at the end of the Symbian build process, there is a tool, called PETRAN, which converts your PE file to E32 file.

e32overview.gif

Figure 1 shows the overview of E32 file format. It starts with the header, like all other executable format. I will explain what is insider the header. After the header there are some sections, i.e.:

-  Code section, contains three parts, text section, export address table and import address table. The text section contains all the object files (.obj) of all your source code. The export address table lists all the exported functions you have in your program. The import address table lists all the imported functions used in your program.
-  BSS section, contains un-initialized data. This section is usually not available in most Symbian applications.
-  Data section, contains initialized data. Since most Symbian applications are .app or .dll format, this section usually does not exist either.
-  Import section, contains the information about all imported functions used by your program.
-  Relocation section, contains relocation table needed by Symbian loader to load your program.

Header Information

Now let's start to take a look at the E32 header. The following code is copied from the header file, E32Image.h, distributed by Symbian in their build tools (see the link at the end of this article).

class E32ImageHeader
   {
public:
   TUint32 iUid1;
   TUint32 iUid2;
   TUint32 iUid3;
   TUint32 iCheck;
   TUint iSignature; // 'EPOC'
   TCpu iCpu; // 0x1000 = X86, 0x2000 = ARM, 0x4000 = M*Core
   TUint iCheckSumCode; // sum of all 32 bit words in .text
   TUint iCheckSumData; // sum of all 32 bit words in .data
   TVersion iVersion;
   TInt64 iTime;
   TUint iFlags; // 0 = exe, 1 = dll, +2 = no call entry points
   TInt iCodeSize; // size of code, import address table, constant data and export dir
   TInt iDataSize; // size of initialized data
   TInt iHeapSizeMin;
   TInt iHeapSizeMax;
   TInt iStackSize;
   TInt iBssSize;
   TUint iEntryPoint; // offset into code of entry point
   TUint iCodeBase; // where the code is linked for
   TUint iDataBase; // where the data is linked for
   TInt iDllRefTableCount; // filling this in enables E32ROM to leave space for it
   TUint iExportDirOffset; // offset into the file of the export address table
   TInt iExportDirCount;
   TInt iTextSize; // size of just the text section
   TUint iCodeOffset; // file offset to code section
   TUint iDataOffset; // file offset to data section
   TUint iImportOffset; // file offset to import section
   TUint iCodeRelocOffset; // relocations for code and const
   TUint iDataRelocOffset; // relocations for data
   TProcessPriority iPriority; // priority of this process
   };

-   TUint32 iUid1, TUint32 iUid2, TUint32 iUid3, represent the identifiers that uniquely identify your program. The first UID can be thought of as a system level identifier, for example 0x10000079 for DLLs and 0x1000007A for executables. The second UID distinguishes between objects having the same iUid1, for example 0x100039CE for polymorphic interface DLLs and 0x1000008d for static interface (shared library). The third UID can be thought of as a program identifier. Usually you have to ask the third identifier directly to Symbian by sending an email to them. However, there are also some UID for testing, which can be chosen from the range 0x0100000 to 0x0FFFFFF.
-  TUint32 iCheck, is the checksum of the first three UIDs. There is a tool in Symbian SDK, called uidcrc.exe, which allows you to generate checksum from the first three UIDs. For example, the following command will generate checksum for the UIDs of 0x1000079, 0x1000029CE and 0x00DD3103.
C:/>uidcrc 0x10000079 0x100039ce 0x00dd3103
0x10000079 0x100039ce 0x00dd3103 0xae035303

-   TUint iSignature, is a unique signature of E32 file, always has a value 'EPOC'.
-  TCpu iCpu, the platform of the programs, usually has a value ECpuX86 = 0x1000 for the Intel processor and ECpuArm = 0x2000 for the ARM processor.
-  TUint iCheckSumCode, is checksum of the code section. According to the comments in the header files, this is the sum of all 32 bit words in .text section. However, from my experience it is actually the sum of all 32 bits words in the code section, including import address table and export table (= iCodeSize field).
-  TUint iCheckSumData, is checksum of all 32 bit words in the .data section. Since we usually build our programs to .app or .dll in Symbian, this checksum is usually zero.
-  TVersion iVersion, the version of PETRAN used to generate this E32 file. For example, if you are using UIQ 2.1, the version is 1.00(175).
-  TInt64 iTime, is the timestamp when the program was built.
-  TUint iFlags, is a flag with the value 0 for .exe, 1 for .dll and +2 for no call of entry points.
-  TInt iCodeSize, the size of the code section, including import address table, constant data and export address table.
-  TInt iDataSize, the size of the initialized data section. Like iCheckSumData, for most cases we will find that this field has the value 0.
-  TInt iHeapSizeMin, the minimum size of the heap.
-  TInt iHeapSizeMax, the maximum size of the heap.
-  TInt iStackSize, the size of the stack.
-  TInt iBssSize, the size of the un-initialized data section.
-  TUint iEntryPoint, the offset into code of entry point.
-  TUint iCodeBase, where the code is linked for.
-  TUint iDataBase, where the data is linked for.
-  TInt iDllRefTableCount, the number of DLLs imported by this program.
-  TUint iExportDirOffset, the offset of the export address table.
-  TInt iExportDirCount, the number of functions exported by this program.
-  TInt iTextSize, the size of the text section, i.e. the size of all the object files compiled from your source code.
-  TUint iCodeOffset, the file offset to the code section.
-  TUint iDataOffset, the file offset to the data section. As I have explained above, since we usually deal with .app or .dll, this field usually has the value 0.
-  TUint iImportOffset, the file offset to the import section.
-  TUint iCodeRelocOffset, relocation offset for code and constant.
-  TUint iDataRelocOffset, relocation offset for data.
-  TProcessPriority iPriority, the priority of this process, for normal applications the value is EPriorityForeground, it means priority for the foreground tasks.

Example

To have a better understanding what the above fields are all about, I will give a simple example. We will compile Hello World example of UIQ SDK 2.1 and then take a look at the E32 image header. Firstly, you have to compile the Hello World example with the standard Symbian build command.

C:/Symbian/UIQ_21/examples/HelloWorld>bldmake bldfiles

C:/Symbian/UIQ_21/examples/HelloWorld>abld build armi urel
Now go to /epoc32/release/armi/urel directory and use PETRAN tool to read the E32 image header information of your Hello World program. You can of course write your own program and read the header files. Here I use PETRAN to make our life easier. As I have explained above, PETRAN is basically a tool that converts PE file format (the output of GCC compiler) to Symbian specific file format (E32 file format). You can also use PETRAN to display the information of any E32 files, like we are going to do. Simply type the following command to run PETRAN on your Hello World. C:/Symbian/UIQ_21/epoc32/release/armi/urel>petran helloworld.app

You will get the following result in your screen. I do not copy the whole output since some of the outputs are not really important for us. The comments explain which fields of E32 image header the information represent of.

PETRAN - PE file preprocessor V01.00 (Build 175)
Copyright (c) 1996-2001 Symbian Ltd.

E32ImageFile 'helloworld.app'               // file name (not in E32 image header)
V1.00(175) Time Stamp: 00e0be89,69063b40    // iVersion iTime
EPOC Dll for ARM CPU                        // iCpu
Entry points are not called                 // iFlags
Uids: 10000079 100039ce 10008ace (7ec529db) // iUid1, iUid2, iUid3 and iCheck
File Size: 00001368                         // file size (not in E32 image header)
Code Size: 00000ed8                         // iCodeSize
Data Size: 00000000                         // iDataSize
Chk code/data: d4ad460a/00000000            // iCheckSumCode iCheckSumData
Min Heap Size: 00001000                     // iHeapSizeMin
Max Heap Size: 00100000                     // iHeapSizeMax
Stack Size: 00002000                        // iStackSize
Code link addr: 10000000                    // iCodeBase
Data link addr: 00000000                    // iDataBase
Code reloc offset: 00001194                 // iCodeRellocOffset
Data reloc offset: 00000000                 // iDataRellocOffset
Dll ref table count: 4                      // iDllRefTableCount
Offset Size Relocs NumOfRelocs
Code 00007c 000ed8                          // iCodeOffset, iCodeSize
    001194 0000e1 +000000 (entry pnt)      // iCodeRellocOffset .. iEntryPoint
Data 000000 000000                          // iDataOffset iDataSize
Bss 000000                                  // iBssSize
Export 000f50 000004 (1 entries)            // iExportDirOffset iExportDirCount
Import 000f54                               // iImportOffset

Code (text size=00000d08)                   // iTextSize

...                                         // here the dump of the text section

225 relocs

...                                         // here the dump of the relocation section

Idata Size=00000240
Offset of import address table (relative to code section): 00000d08

...                                        // here the import tables information

Figure 2 below shows the sections in Hello World application are structured. On the left side you can see the offset of each section. For example, iCodeOffset (= 0x7C) is the offset of the code section. I won't explain the offsets in more details because all information is stored in the header.

e32example.gif

On the right side you can see the size of each section. The size is a little bit tricky because not all information is stored in the header. The size of E32ImageHeader can be calculated easily using sizeof operator. The size of text section is straightforward as well since the information is available in the header, iTextSize. The same holds for the size of code section, iCodeSize.

Calculating the size of the export table is a little bit more complicated. You need to multiple iExportDirCount to sizeof(UINT). Why? Because each exported function is stored in unsigned integer. In this example you have only 1 exported function, multiplied by sizeof(UINT) and you will get the 4.

Calculating the size of import address table needs some knowledge how the import tables are structured in Symbian. Basically you need to find out how many functions are imported by your program, in this example 114. How do we get this number? If you look at iDllRefTableCount, the Hello World example imports 4 DLLs, to get the number 114 you have to go through these DLLs and count the imported functions for each DLL. Like the export table, you need to multiply it by sizeof(UINT). Note that we have to add 1 to the number of imported functions because there is a null terminated sign at the end of the import table.

The size of import section, 0x0240 can be read from the first 32 bits of the import section. If you open E32Image.h, you will find a structure, called E32ImportSection, with one field, iSize.

class E32ImportSection
   {
public:
   TInt iSize; // size of this section
                  // E32ImportBlock[iDllRefTableCount];
   };

This structure is the first 32 bits in the import section and iSize is the size of the import section.

Like import section, the size of relocation section can be read from the first 32 bits of the relocation section. The structure that stores this information is E32RelocSection, with two fields, i.e. iSize and iNumberOfRelocs.

class E32RelocSection
   {
public:
   TInt iSize; // size of this relocation section
   TInt iNumberOfRelocs; // number of relocations in this section
   };

The field iSize in our Hello World example is 0x01CC. Why do we need to add sizeof(E32RelocSection) to the size of relocation section? Because E32RelocSection.iSize does not include the size of the relocation header. It is a little bit diffrenet with the import section because E32ImportSection.iSize has already included the import header.

That's all folks! I hope you have a better understanding of E32 file structure after reading this article.

Further Reading

-  Portable Executable File Format - A very good introduction about Portable Executable file format in Windows.
-  Microsoft Portable Executable and Common Object File Format Specification - The official specification of Windows PE file format. A very comprehensive specification for you who want to have a very deep understanding.
-  ECompXL (EPOC Compressed Executable Loader) - A development tool that allows you to compress executable files and then decompress them on-the-fly during execution. It contains some information about Symbian executable file format as well.
-  Symbian OS Build Tools - A link to download the source code PETRAN tool from Symbian web site. This is the source where I used to write this article.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值