新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论.NET,C#,ASP,VB技术
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Dot NET,C#,ASP,VB 』 → MS.Net CLR扩展PE结构分析 (4) 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 3958 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: MS.Net CLR扩展PE结构分析 (4) 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     admin 帅哥哟,离线,有人找我吗?
      
      
      
      威望:9
      头衔:W3China站长
      等级:计算机硕士学位(管理员)
      文章:5255
      积分:18407
      门派:W3CHINA.ORG
      注册:2003/10/5

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给admin发送一个短消息 把admin加入好友 查看admin的个人资料 搜索admin在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给admin  访问admin的主页 引用回复这个贴子 回复这个贴子 查看admin的博客楼主
    发贴心情 MS.Net CLR扩展PE结构分析 (4)


    发信人: Nineteen (-_-#!), 信区: DotNET
    标  题: MS.Net CLR扩展PE结构分析 (4)
    发信站: BBS 水木清华站 (Sat Apr  3 20:59:13 2004), 转信

    MS.Net CLR扩展PE结构分析 (4)

    作者:Flier Lu <">flier@nsfocus.com>
    主页:http://www.nsfocus.com
    日期:2003-01-03

    在了解了字段和方法的实现原理后,我们接着来看看CLR中属性和事件的实现原理。
      与物理上存在的字段和方法不同,属性和事件是逻辑上的概念,他们是由编译器在
    编译期通过对特定语法的分析,自动生成模拟函数相应实现功能。因而物理上并不存在
    属性或事件的信息,在CLR一级,他们通过中间索引表被映射到一组方法上。

    6.4.3 属性

      属性(Property)是一种非常方便的信息隐藏和封装的手段,通过特殊语法实现
    与普通字段类似的语义,但内部可以使用函数来提供动态信息获取手段,而不像字段必须
    以物理存在的数据形式静态存在。
      CLR中的属性特性的实现是以如下表结构进行组织的。

         +---------+ 1  1 +-------------+ 1
         | TypeDef |<-----| PropertyMap |--+
         +---------+      +-------------+  | 1 +-------------+
                                           +-->| PropertyDef |
      +--------+ 1  1 +-----------------+  |   +-------------+
      | Method |<-----| MethodSemantics |--+
      +--------+      +-----------------+ *

      PropertyDef表定义了属性的信息。定义方面通过PropertyMap表将属性映射到
    TypeDef表定义的类型上,每个属性映射到一种类型上,每种类型可以有多个属性;
    实现方面通过MethodSemantics将属性映射到多个Method表定义的方法上,
    因为一个属性可能由get/set等多个方法实现。

    6.4.3.1 ttPropertyDef ($17)

      PropertyDef表定义了属性的基本信息。

    constructor TJclClrTablePropertyDefRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FFlags      := Table.ReadWord;
      FNameOffset := Table.ReadIndex(hkString);
      FKindIdx    := Table.ReadIndex(hkBlob);
    end;

      Flags定义了属性的特性

      prSpecialName           =   $0200;     // property is special.  Name describes how.

      // Reserved flags for Runtime use only.
      prReservedMask          =   $f400;
      prRTSpecialName         =   $0400;     // Runtime(metadata internal APIs) should check name encoding.
      prHasDefault            =   $1000;     // Property has default

      prUnused                =   $e9ff;

      prSpecialName和prRTSpecialName类似以前在分析字段时介绍过的fdSpecialName,
    表示此属性的名称对于某些工具或CLR来说是有特殊含义的,一般用来模拟某些语言的特殊语法。
    prHasDefault表示此属性有缺省值存在,可以从常量表(Constant)中通过Parent字段找到。
      NameOffset定义了属性的名字,KindIdx指向一个Blob定义此属性类型的Signature。

      可以看到PropertyDef表中仅仅保存了最简单的属性相关信息,对其归属及实现没有涉及。

    6.4.3.2 ttPropertyMap ($15)

      PropertyMap表实际上是一个映射表,将PropertyDef中定义的属性映射到其归属的
    TypeDef表定义的类型中,这样就可以将属性的归属信息从类型和属性的定义中完全抽象出来,
    后面我们可以看到在事件的定义上也是使用的此中抽象模式。

    constructor TJclClrTablePropertyMapRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FParentIdx       := Table.ReadIndex([ttTypeDef]);
      FPropertyListIdx := Table.ReadIndex([ttPropertyDef]);
    end;

      ParentIdx指向属性表的归属类型,在TypeDef表中定义的一个类型条目。
      PropertyListIdx指向属性表中的一个条目,从此条目开始,到下一个
    PropertyMap条目PropertyListIdx字段指向的属性表条目之间,所有的
    属性表条目都归属于前面定义的类型。这样一来PropertyMap表的一个条目
    就可以将PropertyDef表的一组条目映射到一个类型上,大大节省了空间。

    6.4.3.3 ttPropertyPtr ($16)

      PropertyPtr表是一个相对简单的表,定义了一个属性的间接引用。

    constructor TJclClrTablePropertyPtrRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FPropertyIdx := Table.ReadIndex([ttPropertyDef]);
    end;

      通过PropertyPtr表的一个条目的PropertyIdx可以间接获得一个
    PropertyDef表中的条目。

    6.4.3.4 实现

      实现上,前面分析过的MethodSemantics表,将一个PropertyDef表的条目,
    映射到多个MethodDef表的条目上。这种映射关系,一般是由支持属性的语言如C#
    在编译期间根据属性定义语法,按照一定命名方法自动生成的。

        public int Count
        {
            get
            {
               return _count;
            }
            set
            {
               count = value;
            }
        }

      一般来说,对属性的设置和取值部分,编译器自动增加get_/set_前缀的实现函数。
    如对上面那个简单的Count属性,在实现上可能如下

    .method virtual hidebysig public specialname instance int32 get_Count() {
        // body of getter
    }
    .method virtual hidebysig public specialname instance void set_Count(int32 newCount) {
        // body of setter
    }
    .method virtual hidebysig public instance void reset_Count() {
        // body of refresh method
    }
    // the declaration of the property
    .property int32 Count() {
        .get instance int32 get_Count()
        .set instance void set_Count(int32)
        .other instance void reset_Count()
    }

      注意这里get_Count/set_Count方法就是通过MethodSemantics表映射到Count属性上的,
    其方法的标志位specialname被设置,说明这两个方法的名称是具有特殊意义的,是由编译器根据
    属性名称(Count)以及相关功能(get/set)增加相应前缀(get_/set_)组成的。
      而对于Managed C++等不直接提供属性语法支持的语言,要使用属性就必须完整使用自动生成方法名称,
    或提供类似的模拟方法来支持属性语义。如在Managed C++中,可以这样实现属性

    __gc class MyClass
    {
    public:
       MyClass() : m_size(0) {}
       __property int get_Size() { return m_size; }
       __property void set_Size(int value) { m_size = value; }
       // compiler generates a pseudo data member called Size
    protected:
       int m_size;
    };

      __property关键字说明后面声明的方法是为提供属性支持而符合特殊命名规则的。
    编译器在处理时就可以根据命名规则定义Size属性由get_Size和set_Size方法实现。

      值得一提的是,对于索引属性,即属性定义为类似数组的字段,在实现上是通过给
    get/set方法增加一个参数来表示索引的。而对于public string this[int value]
    形式的索引器(或称之为默认属性),在实现上一般用get_Item/set_Item方法实现。
    因而也就无法在C#之类支持索引器的语言中使用Item属性(命名冲突),如果一定要如此,
    可以使用IndexerNameAttribute特性改变缺省命名,如

      [IndexerName("Value")]
      public string this[int value] {...}

      可以将索引器的实现改为get_Value/set_Value。

    6.4.4 事件

      事件(Event)为组件程序提供了一种回调机制的支持。允许组件的客户程序向组件
    订阅某些自己感兴趣的事件,由组件在相应事件引发时回调客户程序提供的函数,
    完成异步处理。
      CLR中的事件特性的实现是以如下表结构进行组织的。
            +---------+ 1  1 +----------+ 1
            | TypeDef |<-----| EventMap |--+
            +---------+      +----------+  | 1 +----------+
                                           +-->| EventDef |
      +--------+ 1  1 +-----------------+  |   +----------+
      | Method |<-----| MethodSemantics |--+
      +--------+      +-----------------+ *

      EventDef表定义了事件的信息。定义方面通过EventMap表将事件映射到
    TypeDef表定义的类型上,每个事件映射到一种类型上,每种类型可以有多个事件;
    实现方面通过MethodSemantics将属性映射到多个Method表定义的方法上,
    因为一个事件可能由add/remove/raise等多个方法实现。

    6.4.4.1 ttEventDef ($14)

      EventDef表定义了事件的基本信息。

    constructor TJclClrTableEventDefRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FEventFlags   := Table.ReadWord;
      FNameOffset   := Table.ReadIndex(hkString);
      FEventTypeIdx := Table.ReadIndex([ttTypeDef, ttTypeRef, ttTypeSpec]);
    end;

      Flags定义了属性的特性

      evSpecialName           =   $0200;     // event is special.  Name describes how.

      // Reserved flags for Runtime use only.
      evReservedMask          =   $0400;
      evRTSpecialName         =   $0400;     // Runtime(metadata internal APIs) should check name encoding.

      prSpecialName和prRTSpecialName类似以前在分析字段时介绍过的fdSpecialName,
    表示此事件的名称对于某些工具或CLR来说是有特殊含义的,一般用来模拟某些语言的特殊语法。
      NameOffset定义了属性的名字,EventTypeIdx指向TypeDef、TypeRef或TypeSpec表
    中定义的类型,表示此事件的类型。

      可以看到EventDef表中仅仅保存了最简单的事件相关信息,对其归属及实现没有涉及。

    6.4.4.2 ttEventMap ($12)

      EventMap表实际上是一个映射表,将EventDef中定义的事件映射到其归属的TypeDef
    表定义的类型中,这样就可以将事件的归属信息从类型和事件的定义中完全抽象出来,
    前面属性的实现上也是使用的相同模式。

    constructor TJclClrTableEventMapRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FParentIdx := Table.ReadIndex([ttTypeDef]);
      FEventListIdx := Table.ReadIndex([ttEventDef]);
    end;

      ParentIdx指向事件表的归属类型,在TypeDef表中定义的一个类型条目。
      PropertyListIdx指向事件表中的一个条目,使用方法与前面介绍的属性映射表相同。

    6.4.4.3 ttEventPtr ($13)

      EventPtr表是一个相对简单的表,定义了一个事件的间接引用。

    constructor TJclClrTableEventPtrRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FEventIdx := Table.ReadIndex([ttEventDef]);
    end;

      通过EventPtr表的一个条目的EventIdx可以间接获得一个EventDef表中的条目。

    6.4.4.4 实现

      实现上,前面分析过的MethodSemantics表,将一个EventDef表的条目,
    映射到多个MethodDef表的条目上。这种映射关系,一般是由支持事件的语言如C#
    在编译期间根据事件定义语法,按照一定命名方法自动生成的。
      例如对如下这样一个简单的event定义

      public delegate void MyDelegate1();

      public interface I1
      {
        event MyDelegate1 MyEvent;
      }

      public class ExplicitEventsSample : I1
      {
        public event MyDelegate1 MyEvent;  // normal implementation of I1.MyEvent.

        ...
      }

      对于CLR来说,将定义一个MyDelegate1类,从System.MulticastDelegate继承出来

    .class /*02000002*/ public auto ansi sealed MyDelegate1
           extends [mscorlib/* 23000001 */]System.MulticastDelegate/* 01000001 */
    {
    } // end of class MyDelegate1

      然后在定义包括了MyDelegate1事件的类型中,如I1接口中,会增加一个EventMap映射表项,
    定义I1接口与MyDelegate1事件的关联关系;然后编译器将根据事件名称自动生成事件的维护方法,
    事件订阅/注销分别使用add_/remove_前缀。

    .class /*02000003*/ interface public abstract auto ansi I1
    {
      .method /*06000005*/ public hidebysig newslot specialname virtual abstract
              instance void  add_MyEvent(class MyDelegate1/* 02000002 */ 'value') cil managed synchronized
      // SIG: 20 01 01 12 08
      {
        // Method begins at RVA 0x0
      } // end of method I1::add_MyEvent

      .method /*06000006*/ public hidebysig newslot specialname virtual abstract
              instance void  remove_MyEvent(class MyDelegate1/* 02000002 */ 'value') cil managed synchronized
      // SIG: 20 01 01 12 08
      {
        // Method begins at RVA 0x0
      } // end of method I1::remove_MyEvent

      .event /*14000001*/ MyDelegate1/* 02000002 */ /*02000002*/ MyEvent
      {
        .addon instance void I1/* 02000003 */::add_MyEvent(class MyDelegate1/* 02000002 */) /* 06000005 */
        .removeon instance void I1/* 02000003 */::remove_MyEvent(class MyDelegate1/* 02000002 */) /* 06000006 */
      } // end of event I1::MyEvent
    } // end of class I1

      注意这里add_MyEvent和remove_MyEvent方法都设置了specialname和hidebysig标志,
    前者说明方法名称是具有特殊意义的,如有编译器根据命名规则自动生成的;后者说明此方法是根据
    方法的signature而非名字进行标示的,避免命名冲突。
      而在具体使用到此事件的地方,如ExplicitEventsSample类中,首先会定义一个字段,
    保存事件订阅情况的维护信息。

    .class /*02000006*/ public auto ansi beforefieldinit ExplicitEventsSample
           extends [mscorlib/* 23000001 */]System.Object/* 01000002 */
           implements I1/* 02000003 */
    {
      .field /*04000001*/ private class MyDelegate1/* 02000002 */ MyEvent

      ...

      然后实现事件的维护方法。这些代码都是有编译器自动生成的。而对于高级用户来说,可以通过事件定义时的
    扩展语法自行提供事件订阅的维护,如

    public delegate int MyDelegate2(string s);

    public interface I2
    {
       event MyDelegate2 MyEvent;
    }

    public class ExplicitEventsSample: I1, I2
    {
       event MyDelegate2 I2.MyEvent   // explicit implementation of I2.MyEvent
       {
          add
          {
             MyEvent2Storage += value;
          }
          remove
          {
             MyEvent2Storage -= value;
          }
       }

       private MyDelegate2 MyEvent2Storage;  // underlying storage for I2.MyEvent.

      ...

      除了对事件的addon/removeon操作外,CLR还提供了fire和other操作的支持。
    前者对应于事件被引发时执行的代码,缺省情况下由编译器自动生成调用事件对象的Invoke方法,
    后者用于其它定制情况,很少使用。
      对于语言一级不提供事件支持的语言如Managed C++来说,事件的使用就比较麻烦了。
    如Managed C++中提供了__event关键字定义事件,__hook和__unhook关键字订阅/退订事件
    __raise关键字引发事件。

    6.5 其它

      在分析完Metadata中结构性的表结构后,我们接着看看一些补充性的表。

    6.5.1 ttCustomAttribute($0C)

      CustomAttribute特性表定义了CLR中元素的自定义约束特性

    constructor TJclClrTableCustomAttributeRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FParentIdx   := Table.ReadIndex([ttModule, ttTypeRef, ttTypeDef, ttFieldDef,
        ttMethodDef, ttParamDef, ttInterfaceImpl, ttMemberRef, ttConstant,
        ttFieldMarshal, ttDeclSecurity, ttClassLayout, ttFieldLayout, ttSignature,
        ttEventMap, ttEventDef, ttPropertyMap, ttPropertyDef, ttMethodSemantics,
        ttMethodImpl, ttModuleRef, ttTypeSpec, ttImplMap, ttFieldRVA, ttAssembly,
        ttAssemblyProcessor, ttAssemblyOS, ttAssemblyRef, ttAssemblyRefProcessor,
        ttAssemblyRefOS, ttFile, ttExportedType, ttManifestResource, ttNestedClass]);
      FTypeIdx     := Table.ReadIndex([ttMethodDef, ttMemberRef]);
      FValueOffset := Table.ReadIndex(hkBlob);
    end;

      ParentIdx指向除CustomAttribute表自身外任意表的项目,定义特性的归属;
      TypeIdx指向一个方法,定义特性的构造函数;
      ValueOffset指向一个Blob数据块,定义特性构造时的参数。

      CustomAttribute表虽然简单,但功能强大、应用广泛,堪称CLR中的瑞士军刀。
    从编译器到程序员,都可以将种种特性附加到CLR的任意元素上,根据特性的类型不同,
    类型构造参数不同,可以变幻出无数众应用来。
      值得注意的是,CLR中定义了一些伪特性,其在程序中以特性相同的语法形式定义,
    而实现上则在编译器一级就进行处理,如AssemblyAlgorithmIdAttribute特性,
    可以定义Assembly签名使用的算法,其在编译期就有编译器进行处理,不反映在实现中。

    6.5.2 ttDeclSecurity($0E)

      MS.NET架构在设计上就充分考虑了安全性,其中对代码访问CLR提供了Assembly、
    类型和方法三级的访问控制策略支持。用户可以给指定对象增加通过访问控制特性定制
    访问策略,既通过System.Security.Permissions.SecurityAttribute与其
    派生类限制/允许特定用户凭据下的对不同资源的访问权限。
      而SecurityAttribute及其派生类在构造时所需关键参数SecurityAction,
    在实现上就是通过DeclSecurity表保存的。

    constructor TJclClrTableDeclSecurityRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FAction              := Table.ReadWord;
      FParentIdx           := Table.ReadIndex([ttTypeDef, ttMethodDef, ttAssembly]);
      FPermissionSetOffset := Table.ReadIndex(hkBlob);
    end;

      Action保存着SecurityAction参数的值;
      ParentIdx指向此SecurityAttribute归属的元素,包括Assembly、
    类型和方法三个层次;
      PermissionSetOffset指向一个Blob,其中以unicode形式保存着
    SecurityAttribute权限集合的XML格式信息。

      用户在程序中静态定义了安全特性后,编译器将根据其信息生成相应XML
    格式权限信息,建立相应DeclSecurity表项目。同时对安全特性归属的元素
    设置其标志的HasSecurity标志,表示在DeclSecurity表中有相应项目。

    6.5.3 ttSignature($11)

      对大多数使用signature的情况,如Field.Signature, Method.Signature等等
    Signature是指向保存在Blob流的一个signature数据块。而对于一些特殊情况,Blob
    中保存的Signature数据可能不被任意一个结构元素所引用,例如IL指令集中calli指令
    (间接函数调用指令,使用函数指针而非指向方法的Token调用,往往用于调用Native方法)
    需要一个Signature描述其调用的函数指针的类型。此时就需要一个StandAloneSig表项,
    指向这个孤儿signature。

    constructor TJclClrTableStandAloneSigRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FSignatureOffset := Table.ReadIndex(hkBlob);
    end;

      唯一的一个域SignatureOffset指向前面所说的孤儿signature。
      CLR通过增加StandAloneSig表项,保证Metadata的完整性。

    6.5.4 ttImplMap($1C)

      为了最大限度保护客户在现有代码上的投资,MS.Net提供了各种与现有代码互操作的方法,
    而在CLR一级,这类对Native代码的调用,是使用ImplMap表项将方法映射到现有代码上。

    constructor TJclClrTableImplMapRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FMappingFlags       := Table.ReadWord;
      FMemberForwardedIdx := Table.ReadIndex([ttFieldDef, ttMethodDef]);
      FImportNameOffset   := Table.ReadIndex(hkString);
      FImportScopeIdx     := Table.ReadIndex([ttModuleRef]);
    end;

      MappingFlags定义了函数的各种属性,稍后详谈;
      MemberForwardedIdx指向FieldDef或MethodDef表中项目,
    定义此实现映射是处理哪个方法的;
      ImportNameOffset指向方法的名称;
      ImportScopeIdx指向方法所在的模块。

      ImplMap表项的标志主要分为四个部分

      pmNoMangle          = $0001;   // Pinvoke is to use the member name as specified.

      // Use this mask to retrieve the CharSet information.
      pmCharSetMask       = $0006;
      pmCharSetNotSpec    = $0000;
      pmCharSetAnsi       = $0002;
      pmCharSetUnicode    = $0004;
      pmCharSetAuto       = $0006;


      pmBestFitUseAssem   = $0000;
      pmBestFitEnabled    = $0010;
      pmBestFitDisabled   = $0020;
      pmBestFitMask       = $0030;

      pmThrowOnUnmappableCharUseAssem   = $0000;
      pmThrowOnUnmappableCharEnabled    = $1000;
      pmThrowOnUnmappableCharDisabled   = $2000;
      pmThrowOnUnmappableCharMask       = $3000;

      pmSupportsLastError = $0040;   // Information about target function. Not relevant for fields.

      // None of the calling convention flags is relevant for fields.
      pmCallConvMask      = $0700;
      pmCallConvWinapi    = $0100;   // Pinvoke will use native callconv appropriate to target windows platform.
      pmCallConvCdecl     = $0200;
      pmCallConvStdcall   = $0300;
      pmCallConvThiscall  = $0400;   // In M9, pinvoke will raise exception.
      pmCallConvFastcall  = $0500;

      pmCharSet*标志定义本机代码函数调用时使用的字符模式。Ansi和Unicode模式
    对应于窄字符或宽字符模式,Auto模式由系统自动判断,NotSpec模式基本上等同于Ansi模式;

    MSDN中说明如下:

      Ansi    以 ANSI 1 字节字符形式封送字符串。
      Auto    针对目标系统适当地自动封送字符串。在 Windows NT 和 Windows 2000 上默认为 Unicode,在 Windows 98 上默认为 Ansi。
      None    此值已过时,它现在与 CharSet.Ansi 具有相同的行为。
      Unicode 以 Unicode 2 字节字符形式封送字符串。

      pmThrowOnUnmappableChar*标志处理字符格式错误的情况;
      pmCallConv*标志定义本机代码函数调用时使用的参数传递方式;

    MSDN中说明如下:

      Cdecl     调用方清理堆栈。它使您能够调用具有 varargs 的函数。
      FastCall  此版本的 .NET 框架不支持该调用约定。
      StdCall   被调用方清理堆栈。它是从托管代码调用非托管函数的默认约定。
      ThisCall  第一个参数是 this 指针,它存储在寄存器 ECX 中。其他参数被推送到堆栈上。此调用约定用于对从非托管 DLL 导出的类调用方法。
      Winapi    使用默认平台调用约定。例如,在 Windows 上它为 StdCall,在 Windows CE 上它为 Cdecl。

      pmBestFit标志指定自动修改非托管 DLL 中的入口点的名称的功能,如开启
    DllImportAttribute.ExactSpelling功能则根据DllImportAttribute.CharSet
    自动在函数名后添加'A'或'W'后缀。
      pmSupportsLastError标志指定被调用方在从属性化方法返回之前将调用 Win32 API SetLastError。
      pmNoMangle标志指示CLR直接使用成员名称,而不处理名字Mangle操作。

    6.5.5 ttNestedClass ($29)

      虽然MS.NET缺省几种语言如C#没有提供嵌套类的支持,但CLR中还是提供了支持,
    通过ttNestedClass表,可以很方便定义两个类的嵌套关系

    constructor TJclClrTableNestedClassRow.Create(const ATable: TJclClrTable);
    begin
      inherited;

      FNestedClassIdx    := Table.ReadIndex([ttTypeDef]);
      FEnclosingClassIdx := Table.ReadIndex([ttTypeDef]);
    end;

      NestedClassIdx和EnclosingClassIdx分别指向嵌套类的内部和外部类。

    6.5.6 其它

      除了前面介绍过的Metadata表之外,还有一些未公开的表。如ttENCLog($1E)和
    ttENCMap($1F)处理ENC相关信息;ttMethodSpec($2B)起到与ttTypeSpec($1B)
    类似的功能,指向一个Signature;ttGenericPar($2A)则被用于处理C#的泛型编程模型支持
      目前Metadata表的编号只使用到了$2B,以后MS可能会根据需要再添加新的功能。

    6.6 小结

      至此,对Microsoft .NET Framework架构下,CLR运行所需的静态信息结构,在PE可执行文件
    中的存储形式,Metadata的分析告一段落。
      因为时间仓促、准备不足、水平有限,文中难免有错误或遗漏的地方,希望大家不吝指正。

    6.7 附录

    6.7.1 参考资料

      1. <Common Language Infrastructure (CLI) Partition II:
          Metadata Definition and Semantics>, Microsoft Corp.
         MS.Net Framework SDK安装目录中Tool Developers Guide\docs\
         子目录中可以找到此文档以及相关文档

      2. MSDN (2002.10/2003.1/for VS.Net/for .Net Framework)

      3. <Applied .NET Framework Programming>, Jeffrey Richter

      4. mono/mcs, Ximian Inc., www.go-mono.com

    6.7.2 源代码

      本文中分析所用源程序是属于JCL项目的一部分,主要由JclCLR, JclMetadata,
    JclCIL, JclDotNet四个单元组成,目前由我维护。有兴趣的朋友可以使用FreeVCS
    版本控制工具从demos.href.com下载最新版本,或来信向我索取(flier@nsfocus.com)。

    6.7.3 Metadata 表索引

        JclMetadata单元处理类名           索引     表名                章节
      ---------------------------------------------------------------------
        TJclClrTableModule              $00 Module                6.2.6
        TJclClrTableTypeRef             $01 TypeRef               6.3.2
        TJclClrTableTypeDef             $02 TypeDef               6.3.1
        TJclClrTableFieldPtr            $03 FieldPtr              6.4.1.1
        TJclClrTableFieldDef            $04 FieldDef              6.4.1.1
        TJclClrTableMethodPtr           $05 MethodPtr             6.4.2.1
        TJclClrTableMethodDef           $06 MethodDef             6.4.2.1
        TJclClrTableParamPtr            $07 ParamPtr              6.4.2.5
        TJclClrTableParamDef            $08 ParamDef              6.4.2.5
        TJclClrTableInterfaceImpl       $09 InterfaceImpl         6.3.5
        TJclClrTableMemberRef           $0a MemberRef             6.4.2.6
        TJclClrTableConstant            $0b Constant              6.4.1.2
        TJclClrTableCustomArttibute     $0c CustomAribute         6.5.1
        TJclClrTableFieldMarshal        $0d FieldMarshal          6.4.1.4
        TJclClrTableDeclSecurity        $0e DeclSecurity          6.5.2
        TJclClrTableClassLayout         $0f ClassLayout           6.4.1.3
        TJclClrTableFieldLayout         $10 FieldLayout           6.4.1.3
        TJclClrTableStandAloneSig       $11 Signature             6.5.3
        TJclClrTableEventMap            $12 EventMap              6.4.4.2
        TJclClrTableEventPtr            $13 EventPtr              6.4.4.3
        TJclClrTableEventDef            $14 EventDef              6.4.4.1
        TJclClrTablePropertyMap         $15 PropertyMap           6.4.3.2
        TJclClrTablePropertyPtr         $16 PropertyPtr           6.4.3.3
        TJclClrTablePropertyDef         $17 PropertyDef           6.4.3.1
        TJclClrTableMethodSemantics     $18 MethodSemantics       6.4.2.3
        TJclClrTableMethodImpl          $19 MethodImpl            6.4.2.4
        TJclClrTableModuleRef           $1a ModuleRef             6.2.6
        TJclClrTableTypeSpec            $1b TypeSpec              6.3.4
        TJclClrTableImplMap             $1c ImplMap               6.5.4
        TJclClrTableFieldRVA            $1d FieldRVA              6.4.1.5
        TJclClrTableENCLog              $1e ENCLog                6.5.6
        TJclClrTableENCMap              $1f ENCMap                6.5.6
        TJclClrTableAssembly            $20 Assembly              6.2.1
        TJclClrTableAssemblyProcessor   $21 AssemblyProcessor     6.2.3
        TJclClrTableAssemblyOS          $22 AssemblyOS            6.2.3
        TJclClrTableAssemblyRef         $23 AssemblyRef           6.2.2
        TJclClrTableAssemblyRefProcessor$24 AssemblyRefProcessor  6.2.3
        TJclClrTableAssemblyRefOS       $25 AssemblyRefOS         6.2.3
        TJclClrTableFile                $26 File                  6.2.4
        TJclClrTableExportedType        $27 ExportedType          6.3.3
        TJclClrTableManifestResource    $28 ManifestResource      6.2.5
        TJclClrTableNestedClass         $29 NestedClass           6.5.5
        TJclClrTable                    $2A GenericPar            6.5.6
        TJclClrTableMethodSpec          $2B MethodSpec            6.5.6
    --
    ——长夜漫漫,无心睡眠……难道狼妹妹也睡不着吗?


    ※ 修改:·Nineteen 于 Apr  3 20:59:28 修改本文·[FROM:     202.206.3.*]
    ※ 来源:·BBS 水木清华站 smth.org·[FROM: 202.206.3.*]
    上一篇
    返回上一页
    回到目录
    回到页首
    下一篇


       收藏   分享  
    顶(0)
      




    ----------------------------------------------

    -----------------------------------------------

    第十二章第一节《用ROR创建面向资源的服务》
    第十二章第二节《用Restlet创建面向资源的服务》
    第三章《REST式服务有什么不同》
    InfoQ SOA首席编辑胡键评《RESTful Web Services中文版》
    [InfoQ文章]解答有关REST的十点疑惑

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2004/11/9 2:25:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Dot NET,C#,ASP,VB 』的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/7/20 10:26:10

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    109.375ms