开发学习之.Net中PE文件的结构(2)

http://www.itjxue.com  2015-07-17 02:00  来源:未知  点击次数: 

  可以看到,在元数据中除了上面我们提到的那些表以外,还有一些用于记录UserString,Guid的堆数据,后面会提到。

  (2)元数据中的父子关系

  元数据中包含很多“父子关系”,如“类--方法”、“方法--参数”等等。如果你想找到和某个父数据对应的所有子数据,遍历这个子数据所在的表可是个糟糕的选择。事实上,对于这种一对多关系,汇编器在构造元数据表的时候,并不仅仅使用数据间的引用关系,而且使用了数据的排列顺序来帮助定位。每个父数据都只含有一个指向其第一个子数据的引用,其子数据的结尾靠下一个父数据的起始引用来定位。这就要求子数据要依照他们的父数据来排序(符合这种条件的元数据被称为“优化的”、“压缩的”元数据,而IL汇编器一般都是生成这种元数据)。下图是书中给出的class-method父子关系的元数据表示意图:

  开发学习之.Net中PE文件的结构_IT教学网itjxue.com整理

  (3)元数据结构

  前面曾经提到过,元数据其实就是一个二进制的数据块,所以元数据的内部,就是一个个的named stream。这些stream又分为两种类型,除了前面提到过的Table,还有一类是以Heap的形式体现(见上文代码段中的注释)。下图是书中给出的一个完整的元数据结构图:

  开发学习之.Net中PE文件的结构_IT教学网itjxue.com整理

  上面以#开头的就是元数据中可能出现的6个命名流,他们的用途分别是

  #Strings:用来存储元数据项的名字,如类名、方法名等 //Heap Stream

  #Blob: 用来存储一些内部的对象实例,如默认值什么的 //Heap Stream

  #US: 用户定义的字符串常量 //Heap Stream

  #GUID: 包含各种全局统一标志符 //Heap Stream

  #~: “优化的”、“压缩的”元数据,里面的元数据表以优化方式存储(我们在父子关系中刚刚提到过的) //Table Stream

  #-: 非优化的元数据(和#~不能共存) //Table Stream

  其中(#~或#-)、#GUID、#Strings是必不可少的。

  另外,元数据既然被存储在很多表里,那么CLR是如何定位一个元数据项的呢(怎么样定位到某个表的某一行)?这里,它使用了一种叫做Token的机制,每个token占4个字节,其中高位字节表示表序号,剩余三个字节表示表内的行序号。具体这些序号被称为RID(record index),其中行序号从1开始,表序号从0开始。

(责任编辑:IT教学网)

更多

推荐ASP.NET教程文章