新的Symbian OS 9 可执行文件格式(E32Image)

来源:互联网 发布:淘宝可以办假的毕业证 编辑:程序博客网 时间:2024/06/15 13:42

新的Symbian OS 9 可执行文件格式(E32Image)

翻译:加百力(看雪论坛 嵌入式平台安全 版主)

 

        Symbian已经发布了Symbian OS 9。在这个新版中引入了很多新的特性和改变。其中一个改变就是引入了新的可执行文件格式(E32Image)。这篇文章介绍了这种新格式。如果你想了解早期Symbian OS 9的格式请阅读我以前的文章。 

在我们开始之前,请注意我们讨论的是针对目标处理器(ARM)的可执行文件,而不是针对模拟器的格式。这是因为模拟器中的可执行文件使用的是不同的格式。如果你对可执行文件格式完全不了解,文章结尾处提供的那些链接将会帮你加深对E32文件格式的了解。

   这篇文章介绍的信息来自Symbian网站和其他Symbian OS 授权商,例如Nokia。尽管我目前在一家移动电话公司工作,但是这篇文章不代表本公司。我将尽我所能保证本文的准确性,但无能保证绝对准确。

 

EABI 介绍

 ABI (Application Binary Interface)格式是由ARM及其合作厂商制订的格式标准。该标准规定了编译器、链接器及其他工具应该如何生成目标文件和可执行文件。该标准允许由不同编译器生成的目标文件配合工作。例如,一种编译器生成的目标文件可以和另一种编译器生成的目标文件组合在一起。EABI (Embedded Application Binary Interface)格式有着相同的功能,它是ABI格式在嵌入式平台的版本。

在撰写本文时有两种编译器可以编译Symbian OS 9 的文件。它们是RVCT (RealView Compilation Tools)和GCCE软件。RVCT是ARM公司生产的产品,其license价值数千美元。而GCCE是由CodeSourcery 制作的免费编译器。正如其名称所暗示的,GCCE基于GNU编译器。

EABI编译器输出ELF(Executable and Linking Format)格式的文件。这和早期的Symbian OS 9不同,早期系统输出的目标文件格式为PE(Portable Executable)格式。但是Symbian OS不能使用标准ELF格式,因为Symbian OS通常在ROM中,体积受到限制。标准ELF格式的文件太大。这就是为什么Symbian要将标准ELF格式改造为Symbian专用的格式。这种格式叫做E32Image。有一个名叫elf2e32.exe的程序可以将ELF格式转换为E32Image。如果你拥有Symbian OS SDK那么这个程序在/epoc32/tools目录下。

图1显示的是Symbian OS 9中新的程序构建顺序。在这里你可以看到,最后的输出文件由elf2e32.exe 转换成Symbian OS指定的格式,也就是E32Image格式。在Symbian站点上还有很多内容丰富的图片。通常你看不到图1所示的流程,因为Symbian OS的构建脚本(比如bldmake和abld)隐藏了这个过程。

新的Symbian OS 9 可执行文件格式(E32Image) - sunny05296 - sunny05296 的博客

  

 

如果你不知道*.dso文件,那么你可以把它理解为早期Symbian OS 9版本和其他平台上的*.lib文件。它提供了从你的代码到DLL之间的接口。

正如我前面说过的,普通的ELF文件太大无法满足移动电话的内存要求。一种减小ELF文件体积的办法是使用函数序号替换函数名。例如,MyFunction()可以使用函数序号1替换。你可能已经想到了,这样做可以大大减小ELF文件的体积,特别是函数名很长的时候,比如ThisIsVeryLongFunction()。这种映射是如何工作的?有一种定义文件(*.def),该文件中保存了序数和函数名之间的映射。

E32Image 概貌

 

现在让我们来看看E32Image的概貌。它看起来和其他标准的可执行文件格式相似,包含有文件头部,代码区块,数据区块,输入区块等等。

新的Symbian OS 9 可执行文件格式(E32Image) - sunny05296 - sunny05296 的博客

  

图2显示了E32文件格式的概貌。同其他可执行文件格式相似,它从文件头开始。在下一节中我们将详细介绍文件头的内容。在文件头的后面有以下区块:

★                      代码区块,包含源代码生成的全部目标文件(*.o)以及所有输出函数的输出地址表。

★                      BSS区块,包含未初始化数据。

★                      数据区块,包含所有初始化数据。

★                      输入区块,包含你的程序使用的全部输入函数信息。

★                     重定位区块,包含当Symbian OS装载你的程序时所需的重定位表信息。

 

E32Image 头部

 

文件头部信息也许是最有趣的部分,因为它包含了可执行文件的很多信息。E32Image头的定义可以在/epoc32/incl?/f32image.h文件中找到。请查看E32ImageHeaderV类。这是一个E32Image文件格式通常使用的完整的头。如果你仔细查看E32ImageHeaderV这个类,会发现它是由E32HeaderComp派生的。而E32HeaderComp 又是从E32ImageHeader中派生而来的。 查看图3,可以了解这个过程。

新的Symbian OS 9 可执行文件格式(E32Image) - sunny05296 - sunny05296 的博客

  

下面的代码片断显示了EImageHeader, EImageHeaderComp 和E32ImageHeaderV的定义。请注意我删除了一些f32image.h文件中的函数和注释信息,以便使描述更清楚。

class E32ImageHeader
{
p lic:
TUint32 iUid1;
TUint32 iUid2;
TUint32 iUid3;
TUint32 iUidChecksum;
TUint iSignature;            // 'EPOC'
TUint32 iHeaderCrc;          // 整个头部的CRC-32 校验码
TUint32 iModuleVersion;      // 该可执行文件的版本号(链接时决定)
TUint32 iCompressionType;    // 压缩类型(UID或者0 表示未压缩)
TVersion iToolsVersion;      // 生成此文件的PETRAN/ELFTRAN的版本
TUint32 iTimeLo;
TUint32 iTimeHi;
TUint iFlags;                 // 0 = exe, 1 = dll, 2 = 固定地址的exe
TInt iCodeSize;               // 代码区块大小, 输入地址表, 常数和输出目录
TInt iDataSize;               // 初始化数据大小
TInt iHeapSizeMin;
TInt iHeapSizeMax;
TInt iStackSize;
TInt iBssSize;
TUint iEntryPoint;           // 代码入口点偏移量
TUint iCodeBase;             // 代码连接位置
TUint iDataBase;             // 数据连接的位置
TInt iDllRefTableCount;      // 填充此项,启用E32ROM 为程序释放空间
TUint iExportDirOffset;      // 输出地址表在在文件中的偏移量
TInt iExportDirCount;
TInt iTextSize;              // 文件区块大小, also do les as the offset for the
                             // iat w.r.t. the code section
TUint iCodeOffset;          // 代码区块的文件偏移量。头部长度的两倍
TUint iDataOffset;          // 数据区块的文件偏移量
TUint iImportOffset;        // 输入区块的文件偏移量
TUint iCodeRelocOffset;     // 代码和常量重定位
TUint iDataRelocOffset;     // 数据重定位
TUint16 iProcessPriority;   // 执行权限
TUint16 iCpuIdentifier;     // CPU标示符 0x1000 = X86, 0x2000 = ARM
};

class E32ImageHeaderComp : p lic E32ImageHeader
{
p lic:
TUint32 iUncompressedSize; // 未压缩文件大小
// 对于J格式,这是文件大小 - sizeof(E32ImageHeader)
// 这包含有压缩数据 :-(
// 对于其他格式这是文件头大小-整个头部大小
};

class E32ImageHeaderV : p lic E32ImageHeaderComp
{
p lic:
SSecurityInfo iS;

// 使用iSpare1作为异常描述符的偏移量
TUint32 iExceptionDescriptor; // 以字节为单位的从代码区块到异常描述符的偏移量
                              // 如果比特0被置位则有效
TUint32 iSpare2;
TUint16 iExportDescSize;   // 位图区块大小
TUint8 iExportDescType;    // 在输出表中孔洞描述的类型
TUint8 iExportDesc[1];     // 输出表中孔洞的表示-扩展
};

    我将会逐个解释上面介绍区域。列表左端的数字表示以文件起始位置为参考的偏移量。比如iUid2相对于文件头的偏移量为0x04。换句话说,如果你使用二进制编辑器打开可执行文件到偏移量0x04位置,你将会找到iUid2。注意E32Image使用小端顺序。

E32ImageHeader

 

0x00: iUid1,是可执行文件的第一个UID。第一个UID可以被看作是系统级标示符。例如:0x1000 0079表示DLL而0x1000 007A表示可执行文件。如果想了解Symbian OS更多UID的含义请查看这里

0x04: iUid2,是可执行文件的第二个UID。第二个 I用于区分有相同的第一个UID的文件。比如0x1000 39CE表示多态接口的DLL而0x1000 008d表示静态接口(共享库)。

0x08: iUid3,是可执行文件的第三个UID。对于每个应用程序它是对一无二的。开发者必须向Symbian Signed 申请这个UID。Symbian OS 9应用程序通常的UID范围在0x2000 000 到 0x2FFF FFFF之间。在Symbian OS SDK(例如S60 SDK 或者 UIQ SDK)的示例代码中这个UID的范围是在0xA000 0000 到 0xAFFF FFFF之间。也有一些UID用于测试,他们在0x0100 0000 到 0x0FFF FFFF之间。

0x0C: iUidChecksum. 是前3个UID的校验和。在Symbian SDK中有一个工具名叫uidcrc.exe,它可以帮助你根据前3个UID生成校验和。例如使用下面的命令将会为0x1000 007A, 0x1000 39CE 和 0xA000 017F 生成校验和。

C:/>uidcrc 0x1000007A 0x100039CE 0xA000017F
0x1000007a 0x100039ce 0xa000017f 0x1e7cca07

0x10: iSignature, 是E32文件独一无二的标志,总是'EPOC'。

0x14: iHeaderCrc, 是整个头部的校验和。它通过CCITT CRC-32算法计算。

0x18: iModuleVersion,表示可执行文件的版本号。这个信息在连接过程中使用。对于S60 SDK 3.0 iModuleVersion 值为10(=0x0000000A)

0x1C: iCompressionType, 表示压缩可执行文件时所使用的压缩库的UID。如果为0表示可执行文件没有被压缩。据我观察目前只有一种压缩算法。也就是RFC 1951中定义的Deflate/H?man算法。Deflate算法对应的UID是KUidCompressionDeflate (=0x101F 7AFC)。请注意在未来可能会有更多的压缩算法。

0x20: iToolsVersion, 生成该文件的ELFTRAN的版本。

0x24: iTimeLo, 生成文件的时间戳的低4字节数据。

0x28: iTimeHi, 生成文件的时间戳的高4字节数据。

0x2C: iFlags, 可执行性标志。在f32image.h文件中定义了多个标志,例如KImageDll, KimageNoCallEntryPoint等等。在E32ImageHeader中定义了一些函数用于解释这些标志。

例如,我们查找到标志有数值0x1200 002A。这个值0x1200 002A来自:0x1000 0000 + 0x0200 0000 + 0x0000 00020 + 0x0000 0008 + 0x0000 00002。如果我们查看f32image.h文件我们会找到:

o                        0x10000000 = KImageImpFmt_PE,可执行文件使用ELF方式引入。

o                        0x02000000 = KImageHdrFmt_V, 有版本支持头部。

o                        0x00000020 = KImageEpt_Eka2, EKA2 可执行文件。

o                        0x00000008 = KImageABI_EABI, 可执行文件是EABI 映像文件。

o                        0x00000002 = KImageNoCallEntryPoint, 没有调用入口点。

0x30: iCodeSize,代码区块大小, 输入地址表, 常数和输出目录

0x34: iDataSize,未初始化数据大小

0x38: iHeapSizeMin, 堆的最小尺寸

0x3C: iHeapSizeMax,堆的最大尺寸

0x40: iStackSize,堆栈大小

0x44: iBssSize,未初始化数据区块大小

0x48: iEntryPoint,代码入口点偏移量

0x4C: iCodeBase,代码连接位置

0x50: iDataBase,数据连接位置

0x54: iDllRefTableCount,程序引入的DLL数量

0x58: iExportDirOffset,文件中导出地址表偏移量

0x5C: iExportDirCount,导出地址表偏移量

0x60: iTextSize,文件区块大小,also do les as the offset for the iat w.r.t. the code section.

0x64: iCodeOffset,代码区块文件偏移量,文件头大小的两倍

0x68: iDataOffset,数据区块文件偏移量

0x6C: iImportOffset,输入表的文件偏移量

0x70: iCodeRelocOffset,代码和常数的重定位信息

0x74: iDataRelocOffset,数据重定位信息

0x78: iProcessPriority,执行权限

0x7A: iCpuIdentifier, CPU标示符。查看下面的列表,所有可能值:

enum TCpu
{
ECpuUnknown=0, ECpuX86=0x1000, ECp rmV4=0x2000, ECp rmV5=0x2001, ECp rmV6=0x2002, ECpuMCore=0x4000
};

E32ImageHeaderComp

 

0x7C: iUncompressedSize,未压缩文件大小。请记住E32Image文件可能会被压缩。

E32ImageHeaderV

 

在查看这个头部之前,有两个额外的类我们需要了解:SCapabilitySet 和 SSSecurityInfo。它们两个的定义都在e32cmn.h中。它们是在Symbian OS 9中引入的,用于保存平台安全信息。例如:功能、安全标示符和厂商标示符。

str t SCapabilitySet
{
enum {ENCapW=2};
TUint32 iCaps[ENCapW];
};

str t SSecurityInfo
{
TUint32 iSecureId;
TUint32 iVendorId;
SCapabilitySet iCaps; // 能力,平台安全
};

让我们回到 E32ImageHeaderV.

0x80: iS.iSecureId,可执行文件安全ID。通常这个值和可执行文件的UID3一致。

0x84: iS.iVendorId,可执行文件厂商ID。对于第三方应用程序,通常是0.

0x88: iS.iCaps.iCaps, 运行可执行文件所需能力。所有Symbian OS所需能力的定义可以在e32capability.h中找到。

enum TCapability
{
ECapabilityTCB = 0,
ECapabilityCommDD = 1,
ECapabilityPowerMgmt = 2,
ECapabilityMultimediaDD = 3,
ECapabilityReadDeviceData = 4,
ECapabilityWriteDeviceData = 5,
ECapabilityDRM = 6,
ECapabilityTrustedUI = 7,
ECapabilityProtServ = 8,
ECapabilityDiskAdmin = 9,
ECapabilityNetworkControl = 10,
ECapabilityAllFiles = 11,
ECapabilitySwEvent = 12,
ECapabilityNetworkServices = 13,
ECapabilityLocalServices = 14,
ECapabilityReadUserData = 15,
ECapabilityWriteUserData = 16,
ECapabilityLocation = 17,
ECapabilitySurroundingsDD = 18,
ECapabilityUserEnvironment = 19,
};

能力的数值表示比特位置。例如ECapabilityTCB表示最低有效位(LSB)。如果LSB被置位那么可执行文件具备TCB能力。

0x90: iExceptionDescriptor,是以字节为单位,从代码区块起点到异常描述符之间的偏移量如果比特0被置位则有效。

0x94: iSpare2, 保留。

0x98: iExportDescSize, 位图区块的大小。

0x9A: iExportDescType[1], 在输出表中孔洞描述的类型

0x9B: iExportDesc[1], 输出表中孔洞的表示

Example

 

为了更好的理解上面讨论的所有区域信息。我们将给出一个简单的例子。我们将编译S60 SDK 3.0中的Hello World例子并且查看E32Image头部。首先你必须使用标准Symbian OS构建命令,编译Hello World Basic例子。

C:/Symbian/9.1/S60_3rd/S60Ex/helloworldbasic>bldmake bldfiles

C:/Symbian/9.1/S60_3rd/S60Ex/helloworldbasic>abld build gcce urel

现在到/epoc32/release/gcce/urel 目录下使用Elf2E32 工具读取Hello World 程序中的E32Image信息。你可以简单的输入下面的命令在你的Hello World程序上运行Elf2E32工具。

C:/Symbian/9.1/S60_3rd/S60Ex/helloworldbasic>elf2e32 --e32input=helloworldbasic.exe

上面的命令将会显示helloworldbasic.exe头部信息、代码区块和输入区块信息。输出信息可能会很长,所以把输出信息保存到一个文件中分析会容易很多:

C:/Symbian/9.1/S60_3rd/S60Ex/helloworldbasic>elf2e32 --e32input=helloworldbasic.exe > helloworldbasic.txt

如果你打开helloworldbasic.txt文件,在文件开始处,你会看到头部信息。我使用绿色写入了一些注释信息以便显示E32ImageHeaderV被引用的各个区域。

E32ImageFile 'helloworldbasic.exe'
V2.00(505) Time Stamp: 00e0eb0a,d2525b80 // iTimeStampHi, iTimeStampLo
EPOC Exe for ARMV5 CPU // iCpuIdentifier = 0x20001 (ARMv5)
Flags: 1200002a // iFlags
Priority Foreground
Entry points are not called
Image header is format 2
Image is compressed using the DEFLATE algorithm // iCompressionType
Uncompressed size 0000b788
Image FPU support : Soft VFP
Secure ID: a000017f // iSecureId
Vendor ID: 00000000 // iVendorId
Capabilities: 00000000 00000000 // iSs.iCaps.iCaps
Exception Descriptor Offset: 00002561 // iExceptionDescriptor
Exception Index Table Base: 00012dfc
Exception Index Table Limit: 000130bc
RO Segment Base: 00008001
RO Segment Limit: 0000a77c
Export Description: Size=000, Type=01 // iExportDescSize = 000 iExportDescType = 01

Export description consistent
Module Version: 10.0 // iModuleVersion
Imports are ELF-style
ARM EABI
Built against EKA2
Uids: 1000007a 100039ce a000017f (1e7cca07)
// iUid1 = 1000007a, iUid2 = 100039ce, iUid3 = a000017f, iUidChecksum = 1e7cca07
Header CRC: 023aca0d // iHeaderCrc
File Size: 0000b788 // iUncompressedSize
Code Size: 0000b0bc // iCodeSize
Data Size: 00000000 // iDataSize
Compression: 101f7afc // iCompressionType
Min Heap Size: 00001000 // iHeapSizeMin
Max Heap Size: 00100000 // iHeapSieMax
Stack Size: 00005000 // iStackSize
Code link addr: 00008000 // iCodeBase
Data link addr: 00400000 // iDataBase
Code reloc offset: 0000b650 // iCodeRelocOffset
Data reloc offset: 00000000 // iDataRelocOffset
Dll ref table count: 10 // iDllRefTableCount
Offset Size Relocs #Relocs
Code 00009c 00b0bc 00b650 00007d +002504 (entry pnt)
// iCodeOffset = 00009c iCodeSize = 00b0bc iCodeRelocOffset = 00b650
Data 000000 000000
// iDataOffset iDataSize
Bss 000000 // iBssSize
Import 00b158 // iImportOffset

这是全部内容,希望大家喜欢这篇文章!

 

进一步阅读:

Symbian OS (E32Image) Executable File Format – 关于早期Symbian OS 9可执行文件格式的文章。

The Executable and Linking Format (ELF) – 关于ELF文件格式的一篇概述。

ARM ELF File Format – 关于ARM ELF 文件格式的更多详细介绍。ARM ELF文件格式同E32Image格式并不完全相同。这篇文章提供了关于E32Image格式基础的有价值信息。

 

http://sunny05296.blog.163.com/blog/static/133371275201072085824399/