Java Card CAP 文件组件分析

来源:互联网 发布:全景地图制作软件 编辑:程序博客网 时间:2024/06/10 01:14

Java Card CAP 文件组件分析

来源:http://www.dreamingfish123.info/?cat=79

Java Card CAP 文件组件分析 00.1

Java Card CAP 文件组件分析 01——Header Component.4

Java Card CAP 文件组件分析 02——Directory Component.7

Java Card CAP 文件组件分析 03——Applet Component.9

Java Card CAP 文件组件分析 04——Import Component.11

Java Card CAP 文件组件分析 05——Constant Pool Component.13

Java Card CAP 文件组件分析 09——Reference Location Component.19

Java Card CAP 文件组件分析 10——Export Component.21

Java Card CAP 文件组件分析 12——Debug Component.24

 

Java Card CAP 文件组件分析 00

2013924fish发表评论阅读评论

JAVA 智能的可执行文件(CAP 文件)是编译多个应用程序(Applet)的生成结果,包含了一个包中定义的所有类和接口,与包之间是一一对应的关系。实际发卡操作时,首先需要将该可执行文件下载至卡片中,并安装需要的应用实例;用户使用该安装的应用实例执行操作功能。

CAP文件包含12个组件:

Component Type

Value

COMPONENT_Header

1

COMPONENT_Directory

2

COMPONENT_Applet

3

COMPONENT_Import

4

COMPONENT_ConstantPool

5

COMPONENT_Class

6

COMPONENT_Method

7

COMPONENT_StaticField

8

COMPONENT_ReferenceLocation

9

COMPONENT_Export

10

COMPONENT_Descriptor

11

COMPONENT_Debug

12


一个完整的CAP文件,除AppletExportDebug组件是可选外,其他均为必选。每个组件封装成一个CAP包,包含在Jar包中。最后在卡上只保留了5个组件:COMPONET_MethodCOMPONET_ClassCOMPONET_ConstantPoolCOMPONET_StaticField COMPONET_Export。其余的组件只是安装时提取有用信息而不在卡中保存。

12个组件中,类class组件保存本应用声明的所有类和接口的信息;方法method组件保存本应用声明的所有方法和接口,method中利用2字节索引index引用类、方法和域;常数池constant pool组件保存method组件引用的所有类、方法和域信息,分为类、实例域、虚方法、父方法、静态域和静态方法6类,每组信息为4个字节;相关地址reference location组件保存method组件中索引的偏移。

对于JavaCard而言,应用程序的下载过程是即CAP文件写入到EEPROM的过程,即是对CAP文件的下载过程。在CAP文件的下载过程中,需要将一部分组件进行解析,同时对referencelocation中指定的位置进行链接,能够链接到method组件中的一个索引号,并根据索引号查找constant pool中保存的、与该索引号对应的类、方法或域在 EEPROM中的实际地址,调用实际地址中存储的数据。也就是说,方法的调用其实是需要两个步骤来实现的:

1.    根据referencelocation中指定的位置进行链接,获取method组件中的索引号;

2.    根据索引号查找constant pool中保存的、与该索引号对应的类、方法或域在EEPROM中的实际地址,调用实际地址中存储的数据。

查看一个CAP文件的组件,可以通过两种方法实现:

·        解压缩软件直接解压得到

·        通过JCK中的capdump将其分解成各个组件

所有的组件均有通用结构格式,如下:

1

2

3

4

5

6

7

component {

    u1 tag      //u1表示无符号单字节类型的数据变量类型;tag为组件索引号,按照上面组件名称的顺序从1至12排列

 

    u2 size     //u2表示无符号双字节的数据变量类型;size为可变长度数组info[]的元素个数

 

    u1 info[]   //数组info[]中含了组件的所有信息,依据各组件属性不同而各不相同

}

注:多字节数据总是按照大端(big-endian)顺序存放。

例如:HelloWorld.cap中的Applet组件:

1

2

0000000: 0300 0e01 0aa0 0000 0062 0301 0c01 0100  .........b......

0000010: 140a                                     ..

第一个03tag,然后是000esize也就是等于15,说明info15个字符,01标示了这是包中的第一个applet0a为该AppletAID的长度,后面的a0 0000 0062 0301 0c01 01即为appletAID,后面的0014是该Appletinstall_method_offset,即当前Applet中的install()Method组件info[]中的偏移,最后以0a结束。

推荐的CAP组件安装顺序:

1.    COMPONENT_Header

2.    COMPONENT_Directory

3.    COMPONENT_Import

4.    COMPONENT_Applet

5.    COMPONENT_Class

6.    COMPONENT_Method

7.    COMPONENT_StaticField

8.    COMPONENT_Export

9.    COMPONENT_ConstantPool

10.  COMPONENT_ReferenceLocation

11.  COMPONENT_Descriptor (optional)

COMPONENT_Debug组件不需要下载到卡内。


 

Java Card CAP 文件组件分析 01—— Header Component

2013915fish发表评论阅读评论

Header组件中包含了该CAP文件的基本信息,其中包括最重要的文件版本信息和包AID值。版本信息用以判断JAVA卡是否支持对该文件的解析。AIDCAP文件的唯一识别,单张JAVA智能卡上不支持装载相同AIDCAP文件。

1

2

3

4

5

6

7

8

9

10

header_component {

    u1 tag

    u2 size

    u4 magic    // 必须为0xDECAFFE

    u1 minor_version

    u1 major_version

    u1 flags    // ACC_INT - 0x01; ACC_EXPORT - 0x02; ACC_APPLET - 0x04

    package_info package

    package_name_info package_name

}

其中CAP File Package Flags

Flags

Value

ACC_INT

0×01

ACC_EXPORT

0×02

ACC_APPLET

0×04

 

1

2

3

4

5

6

package_info {

    u1 minor_version

    u1 major_version

    u1 AID_length

    u1 AID[AID_length]

}

 

1

2

3

4

package_name_info {

    u1 name_length  // 当包内没有定义任何remote interfaces或者remote classes的时候值可以为0

    u1 name[name_length]

}

以 HelloWorld.cap文件中的Header.cap中的信息为例:

0×01 | 0×00 0×13 | 0xDE0xCA 0xFF 0xED | 0×01 | 0×02 | 0×04 |0×00 0×01 | 0×09 | 0xA0 0×00 0×00 0×000×62 0×03 0×01 0x0C 0×01

·        tag: 0×01 COMPONENT_Header

·        size: 0×13 = 19除去tagsize后的大小

·        magic: 0xDECAFFED用以标识JavaCAP文件格式,若一个文件不是以0xDECAFFED开头则肯定不是JavaCard CAP文件,因为它不符合规范

·        minor_version: 0×01次版本号

·        major_version: 0×02主版本号,CAP文件格式的版本号是02.01;如果CAP文件的版本号超出了Java虚拟机所能够处理的有效范围,Java虚拟机将不会处理该CAP文件

·        flag: 0×04包中没有用到int类型、CAP文件中没有Export组件、CAP文件中有Applet组件。

·        package_info:

o    minor_version: 0×00

o    major_version: 0×01

o    AID_length: 0×09

o    AID: 0xA0 0×00 0×00 0×00 0×62 0×03 0×01 0x0C 0×01

对应卡内installer

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

CardApplet* newapplet=new CardApplet();

int iPos = 0;

u1 c1;

 

c1=dataBuffer[iPos];

 

// Read Header Component

 

if(c1!=TAG_HEADER_COMP){

    std::cerr<<"Not an applet!"<<std::endl;

}

else

{

    iPos+=7;

 

    u1 appletMinVer  = dataBuffer[iPos++];

    u1 appletMajVer  = dataBuffer[iPos++];

    u1 appletFlags   = dataBuffer[iPos++];

    u1 packageMinVer = dataBuffer[iPos++];

    u1 packageMajVer = dataBuffer[iPos++];

    u1 aidLength     = dataBuffer[iPos++];

    u1* aid          = new u1[(int)aidLength];

    for(int i=0;i<aidLength;i++)

    {

        aid[i]=dataBuffer[iPos++];

    }

 

    PackageInfo* pi = newPackageInfo(aid,aidLength,packageMajVer,packageMinVer);

    newapplet->pHeader = newHeaderComponent(pi,appletMajVer,appletMinVer,appletFlags);

 

}

分类:JavaCardTech标签:JavaCard


 

Java Card CAP 文件组件分析 02—— Directory Component

2013918fish发表评论阅读评论

Directory组件记录了CAP文件中每个组件的info[]的字节数,以便在下载CAP至卡片时,为这些组件分配存储空间。另外,Directory组件还记录了静态镜像的大小,并与StaticField组件中的信息保持一致。此外,Directroy组件中还包括自定义类型组件的大小。

1

2

3

4

5

6

7

8

9

10

directory_component {

    u1 tag

    u2 size

    u2 component_sizes[12]

    static_field_size_info static_field_size

    u1 import_count

    u1 applet_count

    u1 custom_count

    custom_component_info custom_components[custom_count]

}

1

2

3

4

5

static_field_size_info {

    u2 image_size

    u2 array_init_count

    u2 array_init_size

}

 

1

2

3

4

5

6

costom_component_info {

    u1 component_tag    // 有效值为[128, 255]之间

    u2 size

    u1 AID_length

    u1 AID[AID_length]

}


 HelloWorld.cap中的 Directory.cap为例:
0×02 | 0×00 0x1F | 0×00 0×13 0×00 0x1F 0×00 0x0E 0×00 0×15 0×00 0×36 0×00 0x0C0×00 0×67 0×00 0x0A 0×00 0×13 0×00 0×00 0×00 0x6C 0×00 0×00 | 0×00 0×00 0×000×00 | 0×02 | 0×01 | 0×00
其中:

·        tag:  0×02 COMPONENT_Directory

·        size:  0x1F = 31除去tagsize3个字节,后面还有31个字节的内容

·        component_sizes: Header – 0×13,Directory – 0x1F, Applet – 0x0E, Import – 0×15, ConstantPool – 0×36, Class –0x0C, Method – 0×67, StaticField – 0x0A, ReferenceLocation – 0×13, Export –0×00, Descriptor – 0x6C, Debug – 0×00;若组件大小为0,则该组件不包含在该CAP文件中,除了AppletExportDebug组件,其他的组件大小都不可以为0

·        static_field_size_info:

o   image_size: 0StaticField组件中的image_size相同,是该包在static域里定义的所有字节数

o   array_init_count: 0StaticField组件中的array_init_count相同,是所有需要在包中<clinit>方法中初始化的数组的数量

o   array_init_size: 0 StaticField组件中array_init表中count项的总数,是所有需要在包中<clinit>方法中初始化的字节的数量

·        import_count: 0×02Import组件中的对应值相同,是导入包的数量

·        applet_count: 0×01Applet组件中的对应值相同,是包中定义的applet的数量;若CAP文件中没有Applet组件,则该值为0

·        custom_count: 0×00 custom_components表中条目数,有效值应在[0, 127]之间

对应卡内installer


 

Java Card CAP 文件组件分析 03—— Applet Component

2013918fish发表评论阅读评论

Applet组件用以记录CAP文件中Applet的基本信息。CAP文件中的Applet可以有多个,且相互独立。

1

2

3

4

5

6

7

8

9

applet_component {

    u1 tag

    u2 size

    u1 count    // 包中applet的个数

        {   u1 AID_length

            u1 AID[AID_length]

            u2 install_method_offset

        }   applets[count]

}

 HelloWorld.cap中的 Applet.cap为例:
0×03 | 0×00 0x0E | 0×01 | 0x0A 0xA0 0×00 0×00 0×00 0×62 0×03 0×01 0x0C 0×010×01 0×00 0×14

·        tag: 03 COMPONENT_Applet

·        size: 0x0E = 14

·        count: 01包中有一个applet

·        applets[]:

o   AID_length: 0x0A = 10

o   AID[]: 0xA0 0×00 0×00 0×00 0×62 0×030×01 0x0C 0×01 0×01appletAID

o   install_method_offset: 0×14即当前Applet中的install()Method组件info[]中的偏移。其中,Install()方法是一个静态方法,用以创建当前Applet的类实例,赋予应用软件生命周期开始执行。

在卡内installer中解析Applet组件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

    //Parse applet component

    int iPosa = 0;

#define READU1 readU1(pAppletComponent,&iPosa)

#define READU2 readU2(pAppletComponent,&iPosa)

    if (sizes[TAG_APPLET_COMP-1] !=0)

    {

    u1 appletcount = READU1;

    AppletComponent* pAC = new AppletComponent(appletcount);

    u1 aidlength = 0;

    u1 aid = 0;

    Applet* _a_applet;

    for(int ia=0;ia<(int)appletcount;ia++)

    {

        aidlength = READU1;

        _a_applet = new Applet(aidlength);

        for(int iaid=0;iaid<aidlength;iaid++)

        {

            _a_applet->pAID[iaid] = READU1;

        }

        _a_applet->installMethodOffset = READU2;

        pAC->applets[ia] = _a_applet;

    }

 

    newapplet->pApplet = pAC;

    }

    else

    {

        newapplet->pApplet = NULL;

    }

#undef READU2

#undef READU1

 


 

Java Card CAP 文件组件分析 04—— Import Component

2013918fish发表评论阅读评论

Import组件中存放了所有导入包的AID,便于查询使用。导入包存放了当前Import组件引用的变量和方法,其信息在package_info结构体中存放。

1

2

3

4

5

6

import_component {

    u1 tag

    u2 size

    u1 count

    package_info packages[count]

}

1

2

3

4

5

6

package_info {

    u1 minor_version

    u1 major_version

    u1 AID_length

    u1 AID[AID_length]

}

 HelloWorld.cap中的 Import.cap为例:
0×04 | 0×00 0×15 | 0×02 | 0×03 0×01 0×07 0xA0 0×00 0×00 0×00 0×62 0×01 0×01 |0×00 0×01 0×07 0xA0 0×00 0×00 0×00 0×62 0×00 0×01

·        tag: 04 COMPONENT_Import

·        size: 0×15 = 21 Import组件中除去tagsize3个字节后的总字节数

·        count: 02导入包有两个。该值和Directory Component中的import_count值相同,有效值为[0, 128]之间

·        package_info packages[0]:

o   minor_version: 03

o   major_version: 01

o   AID_length: 07

o   AID[]: 0xA0 0×00 0×00 0×00 0×62 0×010×01

·        package_info packages[1]:

o   minor_version: 00

o   major_version: 01

o   AID_length: 07

o   AID[]: 0xA0 0×00 0×00 0×00 0×62 0×000×01

在卡内installer中解析Import组件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

    //Parse import component

    int iPosimp = 0;

#define READU1 readU1(pImportComponent,&iPosimp)

#define READU2 readU2(pImportComponent,&iPosimp)

    if (sizes[TAG_IMPORT_COMP-1] !=0)

    {

        u1 pcount = READU1;

        COUT<<"Imported package count = "<<(int)pcount<<ENDL;

        ImportComponent* pIC = new ImportComponent(pcount);

 

        for(int ii=0;ii<pcount;ii++)

        {

            u1 packageMinVer = READU1;

            u1 packageMajVer = READU1;

            u1 aidLength     = READU1;

            u1* aid          = new u1[(int)aidLength];

            for(int i=0;i<aidLength;i++)

            {

                aid[i]=READU1;

            }

 

            PackageInfo* pi = new PackageInfo(aid,aidLength,packageMajVer,packageMinVer);

            pIC->packages[ii] = pi;

        }

 

        newapplet->pImport = pIC;

    }

#undef READU2

#undef READU1

 


 

Java Card CAP 文件组件分析 05—— Constant Pool Component

2013918fish发表评论阅读评论

Constant组件是CAP文件的所有组件中最重要的。数据data、方法method和类class使用不同的结构体,JAVA将这些结构体记录于Constant组件中。

1

2

3

4

5

6

constant_pool_component {

    u1 tag

    u2 size

    u2 count    // constant_pool数组中的实例数,有效值在[0, 65535]之间

    cp_info constant_pool[count]

}

 

1

2

3

4

cp_info {

    u1 tag

    u1 info[3]

}

Constant组件中共使用六种类型结构体,他们均是tag结合定位信息的组成形式。tag为结构体类型索引,索引值为16。定位信息用来查询该结构体在CAP文件中的位置,不同类型采用不同的定位方法。

Constant Type

Tag

CONSTANT_Classref

1

CONSTANT_InstanceFieldref

2

CONSTANT_VirtualMethodref

3

CONSTANT_SuperMethodref

4

CONSTANT_StaticFieldref

5

CONSTANT_StaticMethodref

6


和一般的Java类文件相比,Java卡平台的常量类型不仅指定了引用项的类型,还体现了引用方式。例如在Java的常量池里方法引用(method reference)只有一种常量类型,但在Java卡中有三种:VirtualMethodrefSuperMethodrefStaticMethodref

在常量池里的条目没有严格的排序要求,但是推荐CONSTANT_InstanceFieldref常量可以在数组前部,这样可以使用getfield_Tputfield_T字节码,而不是用getfield_T_wputfield_T_w字节码。

以下是对六种类型结构体的具体描述:

CONSTANT_Classref
用来描述一个类或者接口的引用,类或者接口可以在这个包里定义的或者在导入包中。

1

2

3

4

5

6

7

8

9

10

11

CONSTANT_Classref_info {

    u1 tag  // 值为 CONSTANT_Classref(1)

    union {

        u2 internal_class_ref

        {

            u1 package_token

            u1 class_token

        }   external_class_ref

    }   class_ref

    u1 padding

}

·        class_ref:指向该结构体所代表的类或接口,JAVA编程支持将类存于包内或包外,因此在该联合体中有体现,并根据联合体的最高位取值代表内外选择:若是在本包里定义的,则该结构体表示为一个internal_class_ref,且高位bit0;若类和接口是在另一个包里定义的,则表示为一个external_class_ref,且高位bit1

o   internal_class_ref:指当前类在Class组件info[]中的偏移量。值需要在[0, 32767]之间,高位bit0

o   external_class_ref:

§ package_token:指一个包的token,在CAP文件中的Import组件中定义。值需要在[0, 127]之间,高位bit1

§ class_token:指一个类或者接口的token,其值在导入包的Export文件中有定义。

·        padding:值为0,用以补足结构体为4字节的整数倍,以便于存储。

CONSTANT_InstanceFieldref, CONSTANT_VirtualMethodref, CONSTANT_SuperMethodref这三个结构体基本相同:

1

2

3

4

5

CONSTANT_InstanceFieldref_info {

    u1 tag  // 2

    class_ref class

    u1 token

}

1

2

3

4

5

CONSTANT_VirtualMethodref_info {

    u1 tag  // 3

    class_ref class

    u1 token

}

 

1

2

3

4

5

CONSTANT_SuperMethodref_info {

    u1 tag  // 4

    class_ref class

    u1 token

}

区别于CONSTANT_Classref_info,结构体的最后是一个字节的token,用以在类结构的方法表中找到方法的地址。

CONSTANT_StaticFieldref, CONSTANT_StaticMethodref也同样具有相同的结构

1

2

3

4

5

6

7

8

9

10

11

12

13

14

CONSTANT_StaticField_info {

    u1 tag  //5

    union {

        {

            u1 padding

            u2 offset

        }   internal_ref

        {

            u1 package_token

            u1 class_token

            u1 token

        }   external_ref

    }   static_field_ref

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

CONSTANT_StaticMethodref_info {

    u1 tag  // 6

    union {

        {

            u1 padding

            u2 offset

        }   internal_ref

        {

            u1 package_token

            u1 class_token

            u1 token

        }   external_ref

    }   static_method_ref

}

区别于上段提到的三个结构体,token用于Export组件中。

 HelloWorld.cap中的ConstantPool.cap为例:

0×05 | 0×00 0×36 | 0×00 0x0D | 0×02 0×00 0×00 0×00 |0×06 0×80 0×03 0×00 |0×03 0×80 0×03 0×01 | 0×01 0×00 0×00 0×00 | 0×06 0×00 0×00 0×01 | 0×03 0×800x0A 0×01 | 0×03 0×80 0x0A 0×06 | 0×06 0×80 0×10 0×02 | 0×03 0×80 0x0A 0×03 |0×03 0×80 0x0A 0×07 | 0×03 0×80 0x0A 0×09 | 0×03 0×80 0x0A 0×04 | 0×03 0×800x0A 0×05

·        tag: 05 COMPONENT_ConstantPool

·        size: 0×36 = 54

·        count: 0x0D = 13constant_pool[]数组里的条目数,有效数值应当在[0, 65535]之间

·        cp_info constant_pool[0]:

o   tag: 02 CONSTANT_InstanceFieldref

o   info[]: 0×00 0×00 0×00

·        cp_info constant_pool[1]:

o   tag: 06 CONSTANT_StaticMethodref

o   info[]: 0×80 0×03 0×00

·        cp_info constant_pool[2]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0×03 0×01

·        cp_info constant_pool[3]:

o   tag: 01 CONSTANT_Classref

o   info[]: 0×00 0×00 0×00

·        cp_info constant_pool[4]:

o   tag: 06 CONSTANT_StaticMethodref

o   info[]: 0×00 0×00 0×01

·        cp_info constant_pool[5]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0x0A 0×01

·        cp_info constant_pool[6]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0x0A 0×01

·        cp_info constant_pool[7]:

o   tag: 06 CONSTANT_StaticMethodref

o   info[]: 0×80 0×10 0×02

·        cp_info constant_pool[8]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0x0A 0×03

·        cp_info constant_pool[9]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0x0A 0×07

·        cp_info constant_pool[10]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0x0A 0×09

·        cp_info constant_pool[11]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0x0A 0×04

·        cp_info constant_pool[12]:

o   tag: 03 CONSTANT_VirtualMethodref

o   info[]: 0×80 0x0A 0×05

在卡内installer中解析constantpool组件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

    //Parse constant pool component

    int iPosc = 0;

#define READU1 readU1(pConstantPoolComponent,&iPosc)

#define READU2 readU2(pConstantPoolComponent,&iPosc)

    u2 constcount = READU2;

    u1 _c_tag;

    u1 _c_value1;

    u1 _c_value2;

    u1 _c_value3;

    COUT<<"Constant Pool Count = "<<constcount<<ENDL;

    ConstantPoolComponent* pCPC = new ConstantPoolComponent(constcount);

    for(int ic=0;ic<(int)constcount;ic++)

    {

        _c_tag = READU1;

        _c_value1 = READU1;

        _c_value2 = READU1;

        _c_value3 = READU1;

        pCPC->addConst(_c_tag,_c_value1,_c_value2,_c_value3);

    }

 

    newapplet->pConstPool = pCPC;

#undef READU2

#undef READU1

 


 

Java Card CAP 文件组件分析 09—— Reference Location Component

2013924fish发表评论阅读评论

Reference Location组件保存了method组件中索引的偏移。

1

2

3

4

5

6

7

8

reference_location_component {

    u1 tag

    u2 size

    u2 byte_index_count

    u1 offsets_to_byte_indices[byte_index_count]

    u2 byte2_index_count

    u1 offsets_to_byte2_indices[byte2_index_count]

}

helloworld.cap中的RefLocation.cap为例:

0×09 | 0×00 0×13 | 0×00 0×03 | 0x0E 0×26 0x2B | 0×00 0x0C | 0×05 0x0C 0×060×04 0×08 0×05 0×11 0x0C 0×07 0×09 0×06 0×09

·        tag: 09 COMPONENT_ReferenceLocation

·        size: 0×13该组件中除去tagsize3个字节,还有19 bytes的信息。

·        byte_index_count: 03offsets_to_byte_indices数组中的元素数量

·        offsets_to_byte_indices[3]: 0x0E 0×260x2B数组中的值是Method_info的偏移,该偏移位置的值是一个constant_pool[]的下标

·        byte2_index_count: 0x0C

·        offsets_to_byte2_indices[12]: 0×05 0x0C0×06 0×04 0×08 0×05 0×11 0x0C 0×07 0×09 0×06 0×09

在卡内installer中对RefLocation.cap的解析:

1

2

3

4

5

6

7

8

9

10

11

12

13

    //Parse reference location component

    int iPosr = 0;

#define READU1 readU1(pReferenceLocationComponent,&iPosr)

#define READU2 readU2(pReferenceLocationComponent,&iPosr)

    u2 byteIndexCount = READU2;

    COUT<setOffsetsToByte2Indices(byte2IndexCount);

    for(int ir2=0;ir2offsetsToByte2Indices+ir2) = READU1;

    }

 

    newapplet->pRefLoc = pRlc;

 

#undef READU2

#undef READU1

 


 

Java Card CAP 文件组件分析 10—— Export Component

2013924fish发表评论阅读评论

Export组件列出了所有包中可能被其他包中类导入的静态元素,不包括实例域和虚方法。

1

2

3

4

5

6

7

8

9

10

11

12

export_component {

    u1 tag  // COMPONENT_Export (10)

    u2 size

    u1 class_count  // class_exports表中项数,必须大于0

    class_export_info {

        u2 class_offset

        u1 static_field_count

        u1 static_method_count

        u2 static_field_offsets[static_field_count]

        u2 static_method_offsets[static_method_count]

    }   class_exports[class_count]

}

其中class_exports[class_count]为可变长表,若包为一个库包,则表中为每个公共类和公共接口提供一个条目;若包为一个applet包,则表中为包里定义的每个公共可共享的接口提供一个条目。表中特定类或接口的索引值等同于该类或接口的token值,token值在包的Export文件中有列出来。

Export组件需要与class_ref结构体中的external_ref来一起使用。当通过package_token查找到Export组件所在的包之后,再用class_tokenExport组件中找到类信息。

在卡内installer中解析Export.cap

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

    int iPose = 0;

#define READU1 readU1(pExportComponent,&iPose)

#define READU2 readU2(pExportComponent,&iPose)

    if (sizes[TAG_EXPORT_COMP-1] !=0)

    {

        u1 classCount = READU1;

        COUT<<"Class Count = "<<(int)classCount<<ENDL;

 

        ExportComponent *pEC = new ExportComponent(classCount);

 

        for(int _ie=0;_ie<classCount;_ie++)

        {

            u2 _co = READU2;

            u1 _sfc = READU1;

            u1 _smc = READU1;

            pEC->pClassExport[_ie] = new ClassExportInfo(_co,_sfc,_smc);

            for(int _isf=0;_isf<_sfc;_isf++)

            {

                pEC->pClassExport[_ie]->pStaticFieldOffsets[_isf]= READU2;

            }

            for(int _ism=0;_ism<_smc;_ism++)

            {

                pEC->pClassExport[_ie]->pStaticMethodOffsets[_ism]=READU2;

            }

        }

 

        newapplet->pExport = pEC;

    }

 

#undef READU2

#undef READU1

 


 

Java Card CAP 文件组件分析 12—— Debug Component

2013929fish发表评论阅读评论

Debug组件引用了Class组件、Method组件和Static Field组件,而不会被其他组件引用。Debug组件不会被下载到设备中去。

1

2

3

4

5

6

7

8

9

debug_component {

    u1 tag  // COMPONENT_Debug (12)

    u2 size

    u2 string_count     // strings_table[]中的string数

    utf8_info strings_table[string_count]

    u2 package_name_index   //指向strings_table[]的入口

    u2 class_count

    class_debug_info classes[class_count]

}

其中:

1

2

3

4

uft8_info {

    u2 length

    u1 bytes[length]

}

 

1

2

3

4

5

6

7

8

9

10

11

12

13

class_debug_info {  // 包含了类或接口的所有调试信息

    u2 name_index   //包含一个debug_component结构体中strings_table[]项的索引

    u2 access_flags // 2-byte

    u2 location     // 记录这个类或接口的class_info或interface_info在Class组件中info项的字节偏移

    u2 superclass_name_index

    u2 source_file_index

    u1 interface_count

    u2 field_count

    u2 method_count

    u2 interface_names_indexes[interface_count]

    field_debug_info fields[field_count]

    method_debug_info methods[method_count]

}

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

field_debug_info {  // 描述一个类中的一个域

    u2 name_index

    u2 descriptor_index

    u2 access_flags

    union {

        {

            u1 pad1

            u1 pad2

            u1 pad3

            u1 token

        }   token_var

        {

            u2 pad

            u2 location

        }   location_var

        u4 const_value

    }   contents

}

 

1

2

3

4

5

6

7

8

9

10

11

12

method_debug_info {     // 描述一个类中的一个方法

    u2 name_index

    u2 descriptor_index

    u2 access_flags

    u2 location

    u1 header_size

    u2 body_size

    u2 variable_count

    u2 line_count

    variable_info variable_table[variable_count]

    line_info line_table[line_count]

}

spec好长都不想看,可以以后再来补充么。

0 0
原创粉丝点击