日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

[你必须知道的.NET]第二十五回:认识元数据和IL(中)

發(fā)布時(shí)間:2023/12/10 asp.net 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [你必须知道的.NET]第二十五回:认识元数据和IL(中) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
說在,開篇之前
書接上回[第二十四回:認(rèn)識(shí)元數(shù)據(jù)和IL(上)],我們對(duì)PE文件、程序集、托管模塊,這些概念與元數(shù)據(jù)、IL的關(guān)系進(jìn)行了必要的鋪墊,同時(shí)順便熟悉了以ILDASM工具進(jìn)行反編譯的基本方法認(rèn)知,下面是時(shí)候來了解什么是元數(shù)據(jù),什么是IL這個(gè)話題了,我們繼續(xù)。?

很早就有說說Metadata(元數(shù)據(jù))和IL(中間語言)的想法了,一直在這篇開始才算腳踏實(shí)地的對(duì)這兩個(gè)階級(jí)兄弟投去些細(xì)關(guān)懷,雖然來得沒有《第一回:恩怨情仇:is和as》那么迅速,但是Metadata和IL卻是絕對(duì)重量級(jí)的內(nèi)容,值得我們?cè)谌魏螘r(shí)間關(guān)注,本文就是開始。?

??????????????????????????????????????????????????????????????????????????????????????www.anytao.com

?

3 元數(shù)據(jù)是什么?

元數(shù)據(jù),就是描述數(shù)據(jù)的數(shù)據(jù)。這一概念并非CLR之獨(dú)創(chuàng),Metadata存在于任何對(duì)數(shù)據(jù)和數(shù)據(jù)關(guān)系中,例如程序集清單信息也被稱為程序集元數(shù)據(jù)。而不同系統(tǒng)的元數(shù)據(jù)也相應(yīng)具有本身的特點(diǎn),.NET元數(shù)據(jù)也是如此。那么,CLR元數(shù)據(jù)描述的是哪些內(nèi)容呢?正如前文的描述一樣,編譯之后,類型信息將以元數(shù)據(jù)的形式保存在PE格式文件中。.NET是基于面向?qū)ο蟮?#xff0c;所以元數(shù)據(jù)描述的主要目標(biāo)就是面向?qū)ο蟮幕驹?#xff1a;類、類型、屬性、方法、字段、參數(shù)、特性等,主要包括:

  • 定義表,描述了源代碼中定義的類型和成員信息,主要包括:TypeDef、MehodDef、FieldDef、ModuleDef、PropertyDef等。
  • 引用表,描述了源代碼中引用的類型和成員信息,引用元素可以是同一程序集的其他模塊,也可以是不同程序集的模塊,主要包括:AssemblyRef、TypeRef、ModuleRef、MethodsRef等。
  • 指針表,使用指針表引用未知代碼,主要包括:MethodPtr、FieldPtr、ParamPtr等。
  • 堆,以stream的形式保存的信息堆,主要包括:#String、#Blob、#US、#GUIDe等。

如前文所述,我們以ILDasm.exe可以通過反編譯的方式,通過執(zhí)行Ctrl+M快捷鍵來獲取該程序集所使用的MetaData信息列表,在.NET中每個(gè)模塊包含了44個(gè)CLR元數(shù)據(jù)表,如下:

表記錄元數(shù)據(jù)表說明
0(0)ModuleDef描述當(dāng)前模塊
1(0x1)TypeRef描述引用Type,為每個(gè)引用到類型保存一條記錄
2(0x2)TypeDef描述Type定義,每個(gè)Type將在TypeDef表中保存一條記錄
3(0x3)FieldPtr描述字段指針,定義類的字段時(shí)的中間查找表
4(0x4)FieldDef描述字段定義
5(0x5)MethodPtr描述方法指針,定義類的方法時(shí)的中間查找表
6(0x6)MethodDef描述方法定義
7(0x7)ParamPtr描述參數(shù)指針,定義類的參數(shù)時(shí)的中間查找表
8(0x8)ParamDef描述方法的參數(shù)定義
9(0x9)InterfaceImpl描述有哪些類型實(shí)現(xiàn)了哪些接口
10(0xa)MemberRef描述引用成員的情況,引用成員可以是方法、字段還有屬性。
11(0xb)Constant描述了參數(shù)、字段和屬性的常數(shù)值
12(0xc)CustomAttribute描述了特性的定義
13(0xd)FieldMarshal描述了與非托管代碼交互時(shí),參數(shù)和字段的傳遞方式。
14(0xe)DeclSecurity描述了對(duì)于類、方法和程序集的安全性
15(0xf)ClassLayout描述類加載時(shí)的布局信息
16(0x10)FieldLayout描述單個(gè)字段的偏移或序號(hào)
17(0x11)StandAloneSig描述未被任何其他表引用的簽名
18(0x12)EventMap描述類的事件列表
19(0x13)EventPtr描述了事件指針,定義事件時(shí)的中間查找表
20(0x14)Event???????????????描述事件
21(0x15)PropertyMap?????????描述類的屬性列表
22(0x16)PropertyPtr?????????描述了屬性指針,定義類的屬性時(shí)的中間查找表
23(0x17)Property????????????描述屬性
24(0x18)MethodSemantics?????描述事件、屬性與方法的關(guān)聯(lián)
25(0x19)MethodImpl??????????描述方法的實(shí)現(xiàn)
26(0x1a)ModuleRef???????????描述外部模塊的引用
27(0x1b)TypeSpec????????????描述了對(duì)TypeDef或者TypeRef的說明
28(0x1c)ImplMap?????????????描述了程序集使用的所有非托管代碼的方法
29(0x1d)FieldRVA????????????字段表的擴(kuò)展,RVA給出了一個(gè)字段的原始值位置
30(0x1e)ENCLog??????????????描述在Edit-And-Continue模式中哪些元數(shù)據(jù)被修改過
31(0x1f)ENCMap??????????????描述在Edit-And-Continue模式中的映射
32(0x20)Assembly????????????描述程序集定義
33(0x21)AssemblyProcessor???未使用
34(0x22)AssemblyOS??????????未使用
35(0x23)AssemblyRef?????????描述引用的程序集
36(0x24)AssemblyRefProcessor未使用
37(0x25)AssemblyRefOS???????未使用
38(0x26)File????????????????描述外部文件
39(0x27)ExportedType????????描述在同一程序集但不同模塊,有哪些類型
40(0x28)ManifestResource????描述資源信息
41(0x29)NestedClass?????????描述嵌套類型定義
42(0x2a)GenericParam????????描述了泛型類型定義或者泛型方法定義所使用的泛型參數(shù)
43(0x2b)MethodSpec??????????描述泛型方法的實(shí)例化
44(0x2c)GenericParamConstraint描述了每個(gè)泛型參數(shù)的約束

然后是6個(gè)命名堆:

說明

#String一個(gè)AscII string數(shù)組,被元數(shù)據(jù)表所引用,來表示方法名、字段名、類名、變量名以及資源相關(guān)字符串,但不包含string literals。
#Blob包含元數(shù)據(jù)引用的二進(jìn)制對(duì)象,但不包含用戶定義對(duì)象
#US一個(gè)unicode string數(shù)組,包含了定義在代碼中的字符串(string literals),這些字符串可以直接由ldstr指令加載獲取,還記得嗎?我們?cè)凇兜诙?#xff1a;字符串駐留(上)---帶著問題思考》中對(duì)字符串創(chuàng)建過程的論述嗎?
#GUID保存了128byte的GUID值,由元數(shù)據(jù)表引用
#~一個(gè)特殊堆,包含了所有的元數(shù)據(jù)表,會(huì)引用其他的堆。
#-一個(gè)未壓縮的#~堆。除了#-堆,其他堆都是壓縮的。

Note:對(duì)于#String和#US,一個(gè)簡(jiǎn)單的區(qū)別就是:

string hello = "Hello, World";

變量hello名,將保存在#String,而代碼中字符串信息“Hello, World”則被保存在#US中。

關(guān)于元數(shù)據(jù)信息的詳細(xì)描述,例如每個(gè)表包含哪些列,不同表間的關(guān)系,請(qǐng)參考[Standard ECMA-335]和[The .NET File Format]。

在PE文件格式中,Metadata有著復(fù)雜的結(jié)構(gòu),我試圖以數(shù)據(jù)庫管理數(shù)據(jù)的角度出發(fā)來理解元數(shù)據(jù)的結(jié)構(gòu)和關(guān)系,所以表示元數(shù)據(jù)的邏輯結(jié)構(gòu)被成為元數(shù)據(jù)表,類似于數(shù)據(jù)庫表有主鍵和Sechema,元數(shù)據(jù)表以RID(表索引)和元-元數(shù)據(jù)表示類同的概念,以TypeDef表為例,通過數(shù)據(jù)引用關(guān)系同時(shí)與Field、Method、TypeRef等表發(fā)生關(guān)聯(lián),其他表間又有類似的關(guān)系,從而形成一個(gè)復(fù)雜的類數(shù)據(jù)庫結(jié)構(gòu):

因此,元數(shù)據(jù)是保存了類型的編譯后數(shù)據(jù),是.NET程序運(yùn)行的基礎(chǔ),我們可以在運(yùn)行時(shí)動(dòng)態(tài)的以反射的方式獲取元數(shù)據(jù)信息,而這些信息在.NET Framework中以System.Type、MethodInfo等封裝,例如截取MSDN中一個(gè)類間關(guān)系的簡(jiǎn)單示例:

對(duì)于每個(gè)CLR類型而言都可以通過Object.GetType方法返回其Type,從而任意的取到所有的運(yùn)行時(shí)元數(shù)據(jù)信息:

// Release : code04, 2009/02/21 // Author : Anytao, http://www.anytao.com // List : Program.cs private static void ShowMemberInfo() {var assems = AppDomain.CurrentDomain.GetAssemblies();foreach (Assembly ass in assems){foreach (Type t in ass.GetTypes()){foreach (MemberInfo mi in t.GetMembers()){Console.WriteLine("Name:{0}, Type:{1}", mi.Name, mi.MemberType.ToString());}}} }

執(zhí)行上述方法,將獲取一個(gè)長(zhǎng)長(zhǎng)的列表,看到很多熟悉的符號(hào):-)

4 IL是什么?

IL,又稱為CIL或者M(jìn)SIL,翻譯為中文就是中間語言,由ECMA組織(Standard ECMA-335)提供完整的定義和規(guī)范。顧名思義,中間語言正如它的名稱所言,任何與CLR兼容的編譯器所生成的都是中間語言代碼,這是實(shí)現(xiàn)CLR跨語言的基礎(chǔ)結(jié)構(gòu)之一。IL就像一座橋梁,其指令集獨(dú)立于CPU指令而存在,可以由JIT編譯器在運(yùn)行時(shí)翻譯為本地代碼執(zhí)行,連接了任何遵守CLS規(guī)范的高級(jí)語言,為.NET平臺(tái)提供了最基本的支持。在[你必須知道的.NET]一書中,我用一整章(第3章 “一切從IL開始”)的篇幅對(duì)IL的基本內(nèi)容進(jìn)行了相應(yīng)的介紹,所以關(guān)于IL的基礎(chǔ)內(nèi)容例如基本類型、IL分析方法、常見指令、基本運(yùn)算等,就不在本文有所贅述,只對(duì)IL基本內(nèi)容進(jìn)行一點(diǎn)小結(jié):

  • IL是一種面向?qū)ο蟮臋C(jī)器語言,因此具有面向?qū)ο笳Z言的所有特性,類、對(duì)象、繼承、多態(tài)等仍然是IL語言的基本概念。
  • IL指令獨(dú)立于CPU指令,CLR通過JIT編譯機(jī)制將其轉(zhuǎn)換為本地代碼。
  • IL和元數(shù)據(jù)是了解CLR運(yùn)行機(jī)制的重要內(nèi)容,對(duì)于我們打開CLR神秘面紗有著重要的意義。

如前文[初次接觸]部分論述的一樣,可以通過ILDasm.exe或者Reflector工具對(duì)托管代碼執(zhí)行反編譯來查看其IL代碼,對(duì)于很多情況下IL代碼分析可以解決很多高級(jí)語言隱藏的語法糖游戲,例如C#3.0提出的自動(dòng)屬性、隱式類型、匿名類型、擴(kuò)展方法等都可以很快從IL分析中找到答案,所以適當(dāng)?shù)牧私釯L是必要的。那么我們?cè)谙旅鍶IT編譯時(shí)的一個(gè)片段來了解IL代碼對(duì)于托管程序執(zhí)行的作用。

另外,Metadata描述了靜態(tài)的結(jié)構(gòu),而IL闡釋了動(dòng)態(tài)的執(zhí)行,而IL代碼是通過一個(gè)4字節(jié)大小的地址引用元數(shù)據(jù)表的。該引用被稱為元數(shù)據(jù)符號(hào)(Metadata Token,也就是記錄元數(shù)據(jù)表的位置信息),在ILdasm.exe工具中選中“Show token values”,就可以在IL代碼中看到IL代碼通過Metadata Token引用元數(shù)據(jù)表的情況:

.method /*06000003*/ private hidebysig static void Main(string[] args) cil managed {.entrypoint// Code size 36 (0x24).maxstack 2.locals /*11000002*/ init ([0] int32 id,[1] class Anytao.Insidenet.MetadataIL.One/*02000004*/ one,[2] class Anytao.Insidenet.MetadataIL.Two/*02000002*/ two)IL_0000: nopIL_0001: ldc.i4.1IL_0002: stloc.0IL_0003: newobj instance void Anytao.Insidenet.MetadataIL.One/*02000004*/::.ctor() /* 06000007 */IL_0008: stloc.1IL_0009: ldloc.1IL_000a: ldloc.0IL_000b: callvirt instance void Anytao.Insidenet.MetadataIL.One/*02000004*/::set_ID(int32) /* 06000006 */IL_0010: nopIL_0011: newobj instance void Anytao.Insidenet.MetadataIL.Two/*02000002*/::.ctor() /* 06000002 */IL_0016: stloc.2IL_0017: ldloc.2IL_0018: callvirt instance string Anytao.Insidenet.MetadataIL.Two/*02000002*/::SayHello() /* 06000001 */IL_001d: call void [mscorlib/*23000001*/]System.Console/*01000012*/::WriteLine(string) /* 0A000011 */IL_0022: nopIL_0023: ret } // end of method Program::Main

其中,按照ECMA定義的規(guī)范,元數(shù)據(jù)第一個(gè)字節(jié)表示引用的元數(shù)據(jù)表,而其余三個(gè)字節(jié)則表示在相應(yīng)元數(shù)據(jù)表中的記錄,例如06000003表示了引用了MethodDef(06)表的000003項(xiàng)Main方法。

我們可以通過Type的MetadataToken屬性在運(yùn)行時(shí)反射獲取類型的元數(shù)據(jù)符號(hào),例如:

static void Main(string[] args) {Console.WriteLine(typeof(One).MetadataToken); }

?

?

有了上述所有的準(zhǔn)備,我們就可以著手分析元數(shù)據(jù)和IL在程序執(zhí)行時(shí)的角色和關(guān)聯(lián)。

欲知后事如何,且聽下文繼續(xù):-)
  • 《第二十四回:認(rèn)識(shí)元數(shù)據(jù)和IL(上)
  • 》元數(shù)據(jù)和IL在JIT編譯時(shí)

??????????????????????????????????????????????????????????????????????????????????????www.anytao.com


?

支持anytao的創(chuàng)業(yè)產(chǎn)品Worktile
Worktile,新一代簡(jiǎn)單好用、體驗(yàn)極致的團(tuán)隊(duì)協(xié)同、項(xiàng)目管理工具,讓你和你的團(tuán)隊(duì)隨時(shí)隨地一起工作。完全免費(fèi),現(xiàn)在就去了解一下吧。
https://worktile.com

參考文獻(xiàn)

  • 《你必須知道的.NET》第3章 “一切從IL開始”
  • DonBox,《.NET本質(zhì)論》
  • http://www.sloppycode.net/articles/inside-net-assemblies-and-metadata.aspx
  • http://www.codeproject.com/KB/dotnet/dotnetformat.aspx

?

支持(0)?反對(duì)(0)

??

#10樓?2009-02-25 09:57?yy125

關(guān)注中,元數(shù)據(jù)和IL是不是和語言無關(guān)呢,我用vb寫,是不是也生成一樣的元數(shù)據(jù)和IL呢

支持(0)?反對(duì)(0)

??

#11樓?[樓主]?2009-02-25 10:06?Anytao

@yy125?
對(duì),這是.NET跨語言的基礎(chǔ),不同的高級(jí)語言(基于.NET平臺(tái),這是前提)由各自編譯器編譯之后生成的元數(shù)據(jù)和IL是統(tǒng)一的。

支持(0)?反對(duì)(0)

??

#12樓?2009-02-25 23:45?未登錄的包建強(qiáng)

anytao,你這篇寫得確實(shí)不錯(cuò),干凈利落,一針見血。?
下面說但是,?
你用反射來說明元數(shù)據(jù),有點(diǎn)自圓其說。我建議用BinaryStream,代碼如下:?
FileStream s = new FileStream("C:\\mdata\\b.exe", FileMode.Open);?
BinaryReader r = new BinaryReader(s);?

byte a, b;?
a = r.ReadByte();?
b = r.ReadByte();?

哥哥我就是要一個(gè)字節(jié)一個(gè)字節(jié)地去讀exe文件,當(dāng)然,這招兒也是從老外那里學(xué)來的。?
參考文獻(xiàn):http://www.cnblogs.com/Jax/archive/2009/01/02/1366888.html

支持(0)?反對(duì)(0)

??

#13樓?2009-02-25 23:54?未登錄的包建強(qiáng)

@Anders?
《.NET 設(shè)計(jì)規(guī)范--.NET約定、慣用法與模式》,這本書我有,回頭我送你好了,算是給我干女兒的見面禮。?
@胖趙?
就是來攪黃你生意的。娃哈哈。。。

支持(0)?反對(duì)(0)

??

#14樓?[樓主]?2009-02-26 10:26?Anytao

@未登錄的包建強(qiáng)?
不知道說啥了:-)

支持(0)?反對(duì)(0)

??

#15樓?2009-02-26 22:54?波波塔

#String 一個(gè)AscII string數(shù)組 ...?

如果 string 中文test="中文等也是用AscII 存儲(chǔ)在 #string里面的嗎?

支持(0)?反對(duì)(0)

??

#16樓?2009-03-04 21:15?JacksonLin

嚴(yán)重支持

支持(0)?反對(duì)(0)

??

#17樓?2009-12-22 14:49?飛翔的小豬

=============================================
?引用表,描述了源代碼中引用的類型和成員信息,引用元素可以是同一程序集的其他模塊,也可以是不同程序集的模塊,主要包括:AssemblyRef、TypeRef、ModuleRef、MethodsRef等。
=============================================
引用表中應(yīng)該不包括MethodsRef,不存在單獨(dú)的FieldRef和MethodRef,因?yàn)镸emberRef包括了指向字段和方法的引用,你的44個(gè)CLR元數(shù)據(jù)表中也沒有包含,不知道是不是筆誤。
看你的文章要比看專著來的輕松得多。
小弟班門弄斧了。

總結(jié)

以上是生活随笔為你收集整理的[你必须知道的.NET]第二十五回:认识元数据和IL(中)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。