PEReader.cs 72 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677
  1. /*
  2. * PERWAPI - An API for Reading and Writing PE Files
  3. *
  4. * Copyright (c) Diane Corney, Queensland University of Technology, 2004.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the PERWAPI Copyright as included with this
  8. * distribution in the file PERWAPIcopyright.rtf.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY as is explained in the copyright notice.
  12. *
  13. * The author may be contacted at d.corney@qut.edu.au
  14. *
  15. * Version Date: 26/01/07
  16. */
  17. using System;
  18. using System.IO;
  19. using System.Collections;
  20. namespace QUT.PERWAPI
  21. {
  22. /**************************************************************************/
  23. // Class to Read PE Files
  24. /**************************************************************************/
  25. internal class PEReader : BinaryReader
  26. {
  27. private bool x64;
  28. internal static long blobStreamStartOffset = 0;
  29. private static readonly int cliIx = 14;
  30. private Section[] inputSections;
  31. int numSections = 0;
  32. uint[] DataDirectoryRVA = new uint[16];
  33. uint[] DataDirectorySize = new uint[16];
  34. uint[] streamOffsets, streamSizes;
  35. String[] streamNames;
  36. private TableRow[][] tables = new TableRow[MetaData.NumMetaDataTables][];
  37. uint[] tableLengths = new uint[MetaData.NumMetaDataTables];
  38. MetaData md = new MetaData();
  39. MetaDataStringStream userstring;
  40. MetaDataInStream blob, strings, guid;
  41. Sentinel sentinel = new Sentinel();
  42. Pinned pinned = new Pinned();
  43. //CorFlags corFlags;
  44. uint metaDataRVA = 0, metaDataSize = 0, flags = 0;
  45. uint entryPoint = 0, resourcesRVA = 0, resourcesSize = 0;
  46. uint strongNameRVA = 0, strongNameSize = 0, vFixupsRVA = 0, vFixupsSize = 0;
  47. //ushort dllFlags = 0, subSystem = 0;
  48. //uint fileAlign = 0;
  49. //char[] verString;
  50. bool refsOnly = false;
  51. long[] tableStarts;
  52. ResolutionScope thisScope;
  53. PEFileVersionInfo verInfo = new PEFileVersionInfo();
  54. internal Method currentMethodScope;
  55. internal Class currentClassScope;
  56. int genInstNestLevel = 0;
  57. internal bool skipBody = true;
  58. private PEReader(PEFile pefile, System.IO.FileStream file, bool refs, bool skipBody)
  59. :
  60. base(new MemoryStream(new BinaryReader(file).ReadBytes(System.Convert.ToInt32(file.Length))))
  61. {
  62. this.skipBody = skipBody;
  63. thisScope = pefile;
  64. refsOnly = refs;
  65. verInfo.fromExisting = true;
  66. try
  67. {
  68. ReadDOSHeader();
  69. }
  70. catch (PEFileException)
  71. {
  72. Console.WriteLine("Bad DOS header");
  73. return;
  74. }
  75. ReadFileHeader();
  76. ReadSectionHeaders();
  77. ReadCLIHeader();
  78. ReadMetaData();
  79. if (refsOnly)
  80. ReadMetaDataTableRefs();
  81. else
  82. {
  83. ReadMetaDataTables();
  84. pefile.metaDataTables = new MetaDataTables(tables);
  85. }
  86. file.Close();
  87. if (thisScope != null)
  88. {
  89. thisScope.buffer = this;
  90. if (pefile != null)
  91. {
  92. pefile.versionInfo = verInfo;
  93. }
  94. }
  95. strings = null;
  96. userstring = null;
  97. blob = null;
  98. guid = null;
  99. }
  100. private static System.IO.FileStream GetFile(string filename)
  101. {
  102. if (Diag.DiagOn)
  103. {
  104. Console.WriteLine("Current directory is " + System.Environment.CurrentDirectory);
  105. Console.WriteLine("Looking for file " + filename);
  106. }
  107. if (System.IO.File.Exists(filename))
  108. {
  109. return System.IO.File.OpenRead(filename);
  110. }
  111. else
  112. throw (new System.IO.FileNotFoundException("File Not Found", filename));
  113. }
  114. public static PEFile ReadPEFile(string filename, bool skipBody)
  115. {
  116. System.IO.FileStream file = GetFile(filename);
  117. PEFile pefile = new PEFile(filename);
  118. PEReader reader = new PEReader(pefile, file, false, skipBody);
  119. return pefile;
  120. }
  121. internal static ReferenceScope GetExportedInterface(string filename)
  122. {
  123. System.IO.FileStream file = GetFile(filename);
  124. PEReader reader = new PEReader(null, file, true, true);
  125. return (ReferenceScope)reader.thisScope;
  126. }
  127. //internal ResolutionScope GetThisScope() { return thisScope; }
  128. internal string[] GetAssemblyRefNames()
  129. {
  130. string[] assemNames = new string[tableLengths[(int)MDTable.AssemblyRef]];
  131. for (int i = 0; i < assemNames.Length; i++)
  132. {
  133. assemNames[i] = ((AssemblyRef)tables[(int)MDTable.AssemblyRef][i]).Name();
  134. }
  135. return assemNames;
  136. }
  137. internal AssemblyRef[] GetAssemblyRefs()
  138. {
  139. AssemblyRef[] assemRefs = new AssemblyRef[tableLengths[(int)MDTable.AssemblyRef]];
  140. for (int i = 0; i < assemRefs.Length; i++)
  141. {
  142. assemRefs[i] = (AssemblyRef)tables[(int)MDTable.AssemblyRef][i];
  143. }
  144. return assemRefs;
  145. }
  146. /*----------------------------- Reading ----------------------------------------*/
  147. internal void InputError()
  148. {
  149. throw new PEFileException("Error in input");
  150. }
  151. internal void MetaDataError(string msg)
  152. {
  153. msg = "ERROR IN METADATA: " + msg;
  154. if (thisScope != null)
  155. msg = "MODULE " + thisScope.Name() + ": " + msg;
  156. throw new PEFileException(msg);
  157. }
  158. internal Section GetSection(uint rva)
  159. {
  160. for (int i = 0; i < inputSections.Length; i++)
  161. {
  162. if (inputSections[i].ContainsRVA(rva)) return inputSections[i];
  163. }
  164. return null;
  165. }
  166. internal uint GetOffset(uint rva)
  167. {
  168. for (int i = 0; i < inputSections.Length; i++)
  169. {
  170. if (inputSections[i].ContainsRVA(rva))
  171. return inputSections[i].GetOffset(rva);
  172. }
  173. return 0;
  174. }
  175. internal void ReadZeros(int num)
  176. {
  177. for (int i = 0; i < num; i++)
  178. {
  179. byte next = ReadByte();
  180. if (next != 0) InputError();
  181. }
  182. }
  183. private void ReadDOSHeader()
  184. {
  185. for (int i = 0; i < FileImage.PESigOffset; i++)
  186. {
  187. if (FileImage.DOSHeader[i] != ReadByte())
  188. {
  189. InputError();
  190. }
  191. }
  192. uint sigOffset = ReadUInt32();
  193. for (int i = FileImage.PESigOffset + 4; i < FileImage.DOSHeader.Length - 4; i++)
  194. {
  195. if (FileImage.DOSHeader[i] != ReadByte()) { InputError(); }
  196. }
  197. BaseStream.Seek(sigOffset, SeekOrigin.Begin);
  198. if ((char)ReadByte() != 'P') InputError();
  199. if ((char)ReadByte() != 'E') InputError();
  200. if (ReadByte() != 0) InputError();
  201. if (ReadByte() != 0) InputError();
  202. }
  203. private void ReadFileHeader()
  204. {
  205. // already read PE signature
  206. ushort machineid = ReadUInt16();
  207. if (machineid != FileImage.machine && machineid != FileImage.machinex64) InputError();
  208. numSections = ReadUInt16();
  209. uint TimeStamp = ReadUInt32();
  210. ReadZeros(8); /* Pointer to Symbol Table, Number of Symbols */
  211. int optHeadSize = ReadUInt16();
  212. verInfo.characteristics = ReadUInt16();
  213. verInfo.isDLL = (verInfo.characteristics & FileImage.dllFlag) != 0;
  214. /* Now read PE Optional Header */
  215. /* Standard Fields */
  216. ushort magic = ReadUInt16();
  217. if (magic != FileImage.magic && magic != FileImage.magic64) InputError();
  218. x64 = magic == FileImage.magic64;
  219. verInfo.lMajor = ReadByte(); // != FileImage.lMajor) InputError();
  220. verInfo.lMinor = ReadByte(); // != FileImage.lMinor) InputError();
  221. uint codeSize = ReadUInt32();
  222. if (Diag.DiagOn) Console.WriteLine("codeSize = " + Hex.Int(codeSize));
  223. uint initDataSize = ReadUInt32();
  224. if (Diag.DiagOn) Console.WriteLine("initDataSize = " + Hex.Int(initDataSize));
  225. uint uninitDataSize = ReadUInt32();
  226. if (Diag.DiagOn) Console.WriteLine("uninitDataSize = " + Hex.Int(uninitDataSize));
  227. uint entryPointRVA = ReadUInt32();
  228. if (Diag.DiagOn) Console.WriteLine("entryPointRVA = " + Hex.Int(entryPointRVA));
  229. uint baseOfCode = ReadUInt32();
  230. if (Diag.DiagOn) Console.WriteLine("baseOfCode = " + Hex.Int(baseOfCode));
  231. //uint baseOfData = ReadUInt32();
  232. if (!x64)
  233. {
  234. uint baseOfData = ReadUInt32();
  235. if (Diag.DiagOn) Console.WriteLine("baseOfData = " + Hex.Int(baseOfData));
  236. }
  237. /* NT-Specific Fields */
  238. ulong imageBase = x64 ? ReadUInt64() : ReadUInt32();
  239. if (Diag.DiagOn) Console.WriteLine("imageBase = " + Hex.Long(imageBase));
  240. uint sectionAlign = ReadUInt32();
  241. if (Diag.DiagOn) Console.WriteLine("sectionAlign = " + Hex.Int(sectionAlign));
  242. verInfo.fileAlign = ReadUInt32();
  243. if (Diag.DiagOn) Console.WriteLine("fileAlign = " + Hex.Int(verInfo.fileAlign));
  244. verInfo.osMajor = ReadUInt16();
  245. if (Diag.DiagOn) Console.WriteLine("osMajor = " + Hex.Int(verInfo.osMajor));
  246. //ReadZeros(6); // osMinor, userMajor, userMinor
  247. verInfo.osMinor = ReadUInt16();
  248. verInfo.userMajor = ReadUInt16();
  249. verInfo.userMinor = ReadUInt16();
  250. verInfo.subSysMajor = ReadUInt16();
  251. if (Diag.DiagOn) Console.WriteLine("subsysMajor = " + Hex.Int(verInfo.subSysMajor));
  252. verInfo.subSysMinor = ReadUInt16();
  253. ReadZeros(4); // Reserved
  254. uint imageSize = ReadUInt32();
  255. if (Diag.DiagOn) Console.WriteLine("imageSize = " + Hex.Int(imageSize));
  256. uint headerSize = ReadUInt32();
  257. if (Diag.DiagOn) Console.WriteLine("headerSize = " + Hex.Int(headerSize));
  258. uint checkSum = ReadUInt32();
  259. if (Diag.DiagOn) Console.WriteLine("checkSum = " + Hex.Int(checkSum));
  260. verInfo.subSystem = (SubSystem)ReadUInt16();
  261. if (Diag.DiagOn) Console.WriteLine("subSystem = " + Hex.Short((int)verInfo.subSystem));
  262. verInfo.DLLFlags = ReadUInt16();
  263. if (Diag.DiagOn) Console.WriteLine("DLLFlags = " + Hex.Short(verInfo.DLLFlags));
  264. ulong stackReserve = x64 ? ReadUInt64() : ReadUInt32(); // if (ReadUInt32() != FileImage.StackReserveSize) InputError();
  265. ulong stackCommit = x64 ? ReadUInt64() : ReadUInt32(); // if (ReadUInt32() != FileImage.StackCommitSize) InputError();
  266. ulong heapReserve = x64 ? ReadUInt64() : ReadUInt32(); // if (ReadUInt32() != FileImage.HeapReserveSize) InputError();
  267. ulong heapCommit = x64 ? ReadUInt64() : ReadUInt32(); // if (ReadUInt32() != FileImage.HeapCommitSize) InputError();
  268. ReadUInt32(); // if (ReadUInt32() != 0) InputError(); // LoaderFlags
  269. uint numdict = ReadUInt32();
  270. if (numdict != FileImage.NumDataDirectories) InputError();
  271. /* Data Directories */
  272. DataDirectoryRVA = new uint[FileImage.NumDataDirectories];
  273. DataDirectorySize = new uint[FileImage.NumDataDirectories];
  274. for (int i = 0; i < FileImage.NumDataDirectories; i++)
  275. {
  276. DataDirectoryRVA[i] = ReadUInt32();
  277. DataDirectorySize[i] = ReadUInt32();
  278. }
  279. if (Diag.DiagOn)
  280. {
  281. Console.WriteLine("RVA = " + Hex.Int(DataDirectoryRVA[1]) + " Size = " + Hex.Int(DataDirectorySize[1]) + " Import Table");
  282. Console.WriteLine("RVA = " + Hex.Int(DataDirectoryRVA[2]) + " Size = " + Hex.Int(DataDirectorySize[2]) + " Resource Table");
  283. Console.WriteLine("RVA = " + Hex.Int(DataDirectoryRVA[5]) + " Size = " + Hex.Int(DataDirectorySize[5]) + " Base Relocation Table");
  284. Console.WriteLine("RVA = " + Hex.Int(DataDirectoryRVA[12]) + " Size = " + Hex.Int(DataDirectorySize[12]) + " IAT");
  285. Console.WriteLine("RVA = " + Hex.Int(DataDirectoryRVA[14]) + " Size = " + Hex.Int(DataDirectorySize[14]) + " CLI Header");
  286. }
  287. }
  288. private void ReadSectionHeaders()
  289. {
  290. if (Diag.DiagOn) Console.WriteLine("Sections");
  291. inputSections = new Section[numSections];
  292. for (int i = 0; i < numSections; i++)
  293. {
  294. inputSections[i] = new Section(this);
  295. }
  296. }
  297. private void ReadCLIHeader()
  298. {
  299. BaseStream.Seek(GetOffset(DataDirectoryRVA[cliIx]), SeekOrigin.Begin);
  300. uint cliSize = ReadUInt32();
  301. verInfo.cliMajVer = ReadUInt16(); // check
  302. verInfo.cliMinVer = ReadUInt16(); // check
  303. metaDataRVA = ReadUInt32();
  304. metaDataSize = ReadUInt32();
  305. //Console.WriteLine("Meta Data at rva " + PEConsts.Hex(metaDataRVA) + " size = " + PEConsts.Hex(metaDataSize));
  306. verInfo.corFlags = (CorFlags)ReadUInt32();
  307. entryPoint = ReadUInt32();
  308. resourcesRVA = ReadUInt32();
  309. resourcesSize = ReadUInt32();
  310. strongNameRVA = ReadUInt32();
  311. strongNameSize = ReadUInt32();
  312. ReadZeros(8); // CodeManagerTable
  313. vFixupsRVA = ReadUInt32();
  314. vFixupsSize = ReadUInt32();
  315. ReadZeros(16); // ExportAddressTableJumps/ManagedNativeHeader
  316. }
  317. private String ReadStreamName()
  318. {
  319. char[] strName = new char[9];
  320. strName[0] = (char)ReadByte();
  321. char ch = (char)ReadByte();
  322. int i = 1;
  323. while (ch != '\0') { strName[i++] = ch; ch = (char)ReadByte(); }
  324. strName[i++] = '\0';
  325. if (i % 4 != 0)
  326. {
  327. for (int j = 4 - i % 4; j > 0; j--) ReadByte();
  328. }
  329. return new String(strName, 0, i - 1);
  330. }
  331. private void ReadMetaData()
  332. {
  333. if (Diag.DiagOn) Console.WriteLine("MetaData at RVA = " + Hex.Int(metaDataRVA) + " and offset = " + Hex.Int(GetOffset(metaDataRVA)));
  334. BaseStream.Seek(GetOffset(metaDataRVA), SeekOrigin.Begin);
  335. uint sig = ReadUInt32(); // check
  336. verInfo.mdMajVer = ReadUInt16(); // check
  337. verInfo.mdMinVer = ReadUInt16(); // check
  338. ReadZeros(4);
  339. int verStrLen = ReadInt32();
  340. int end = -1;
  341. char[] verString = new char[verStrLen + 1];
  342. for (int i = 0; i < verStrLen; i++)
  343. {
  344. verString[i] = (char)ReadByte();
  345. if ((verString[i] == 0) && (end == -1)) end = i;
  346. }
  347. verString[verStrLen] = (char)0; // check
  348. if (end == -1) end = verStrLen;
  349. verInfo.netVerString = new string(verString, 0, end);
  350. verInfo.SetVersionFromString();
  351. // Beware of unknown netVerString values here ... Needs a better fix (kjg 31-Oct-2007)
  352. GenericParam.extraField = verInfo.netVersion < NetVersion.Whidbey41;
  353. if (Diag.DiagOn && GenericParam.extraField)
  354. {
  355. Console.WriteLine("Version = " + verInfo.netVerString + " has extra field for GenericParam");
  356. }
  357. int alignNum = 0;
  358. if ((verStrLen % 4) != 0) alignNum = 4 - (verStrLen % 4);
  359. ReadZeros(alignNum);
  360. flags = ReadUInt16(); // check
  361. int numStreams = ReadUInt16();
  362. streamOffsets = new uint[numStreams];
  363. streamSizes = new uint[numStreams];
  364. streamNames = new String[numStreams];
  365. if (Diag.DiagOn)
  366. Console.WriteLine("MetaData Streams");
  367. for (int i = 0; i < numStreams; i++)
  368. {
  369. streamOffsets[i] = ReadUInt32();
  370. streamSizes[i] = ReadUInt32();
  371. streamNames[i] = ReadStreamName();
  372. if (Diag.DiagOn)
  373. Console.WriteLine(" " + streamNames[i] + " Offset = " + Hex.Int(streamOffsets[i]) + " Size = " + Hex.Int(streamSizes[i]));
  374. }
  375. uint tildeIx = 0;
  376. for (uint i = 0; i < numStreams; i++)
  377. {
  378. String nam = streamNames[i];
  379. if (MetaData.tildeName.CompareTo(nam) == 0) tildeIx = i;
  380. else
  381. {
  382. uint streamoff = GetOffset(metaDataRVA + streamOffsets[i]);
  383. if (Diag.DiagOn) Console.WriteLine("getting stream bytes at offset " + Hex.Int(streamoff));
  384. BaseStream.Seek(GetOffset(metaDataRVA + streamOffsets[i]), SeekOrigin.Begin);
  385. long streamStart = BaseStream.Position;
  386. byte[] strBytes = ReadBytes((int)streamSizes[i]);
  387. if (MetaData.stringsName.CompareTo(nam) == 0)
  388. {
  389. strings = new MetaDataInStream(strBytes);
  390. }
  391. else if (MetaData.userstringName.CompareTo(nam) == 0)
  392. {
  393. userstring = new MetaDataStringStream(strBytes);
  394. }
  395. else if (MetaData.blobName.CompareTo(nam) == 0)
  396. {
  397. blobStreamStartOffset = streamStart;
  398. blob = new MetaDataInStream(strBytes);
  399. }
  400. else if (MetaData.guidName.CompareTo(nam) == 0)
  401. {
  402. guid = new MetaDataInStream(strBytes);
  403. }
  404. else if (nam.CompareTo("#-") == 0)
  405. {
  406. tildeIx = i;
  407. //throw new Exception("Illegal uncompressed data stream #-");
  408. }
  409. else
  410. {
  411. Console.WriteLine("Unknown stream - " + nam);
  412. }
  413. }
  414. }
  415. // go to beginning of tilde stream
  416. BaseStream.Seek(GetOffset(metaDataRVA + streamOffsets[tildeIx]), SeekOrigin.Begin);
  417. ReadTildeStreamStart();
  418. }
  419. private void SetUpTableInfo()
  420. {
  421. md.CalcElemSize();
  422. tableStarts = new long[MetaData.NumMetaDataTables];
  423. long currentPos = BaseStream.Position;
  424. for (int ix = 0; ix < MetaData.NumMetaDataTables; ix++)
  425. {
  426. tableStarts[ix] = currentPos;
  427. currentPos += tableLengths[ix] * md.elemSize[ix];
  428. }
  429. }
  430. private void ReadTildeStreamStart()
  431. {
  432. if (Diag.DiagOn) Console.WriteLine("Reading meta data tables at offset = " + Hex.Int((int)BaseStream.Position));
  433. // pre: at beginning of tilde stream
  434. ReadZeros(4); // reserved
  435. verInfo.tsMajVer = ReadByte(); // check
  436. verInfo.tsMinVer = ReadByte(); // check
  437. byte heapSizes = ReadByte();
  438. if (heapSizes != 0)
  439. {
  440. md.largeStrings = (heapSizes & 0x01) != 0;
  441. md.largeGUID = (heapSizes & 0x02) != 0;
  442. md.largeBlob = (heapSizes & 0x04) != 0;
  443. }
  444. if (Diag.DiagOn)
  445. {
  446. if (md.largeStrings) Console.WriteLine("LARGE strings index");
  447. if (md.largeGUID) Console.WriteLine("LARGE GUID index");
  448. if (md.largeBlob) Console.WriteLine("LARGE blob index");
  449. }
  450. int res = ReadByte(); // check if 1
  451. ulong valid = ReadUInt64();
  452. ulong sorted = this.ReadUInt64();
  453. if (Diag.DiagOn) Console.WriteLine("Valid = " + Hex.Long(valid));
  454. for (int i = 0; i < MetaData.NumMetaDataTables; i++)
  455. {
  456. if ((valid & FileImage.bitmasks[i]) != 0)
  457. {
  458. tableLengths[i] = ReadUInt32();
  459. tables[i] = new TableRow[tableLengths[i]];
  460. md.largeIx[i] = tableLengths[i] > MetaData.maxSmlIxSize;
  461. if (Diag.DiagOn)
  462. Console.WriteLine("Table Ix " + Hex.Short(i) + " has length " + tableLengths[i]);
  463. }
  464. else tableLengths[i] = 0;
  465. }
  466. if (tableLengths[0] != 1) this.MetaDataError("Module table has more than one entry");
  467. for (int i = 0; i < MetaData.CIxTables.Length; i++)
  468. {
  469. for (int j = 0; j < MetaData.CIxTables[i].Length; j++)
  470. {
  471. if (Diag.DiagOn) Console.WriteLine("CIxTables " + i + " " + j + " tableLength = " + tableLengths[MetaData.CIxTables[i][j]] + " Max = " + MetaData.CIxMaxMap[i]);
  472. md.lgeCIx[i] = md.lgeCIx[i] ||
  473. (tableLengths[MetaData.CIxTables[i][j]] > MetaData.CIxMaxMap[i]);
  474. }
  475. if (Diag.DiagOn) if (md.lgeCIx[i]) Console.WriteLine("LARGE CIx " + i);
  476. }
  477. }
  478. private void SetThisScope()
  479. {
  480. if (refsOnly)
  481. thisScope = Module.ReadModuleRef(this);
  482. else
  483. ((PEFile)thisScope).Read(this);
  484. tables[(int)MDTable.Module][0] = thisScope;
  485. if (tableLengths[(int)MDTable.Assembly] > 0)
  486. {
  487. SetElementPosition(MDTable.Assembly, 1);
  488. if (refsOnly)
  489. {
  490. ModuleRef thisMod = (ModuleRef)thisScope;
  491. thisScope = Assembly.ReadAssemblyRef(this);
  492. //if ((thisMod != null) && (thisMod.ismscorlib) && (thisScope != null)) {
  493. // ((AssemblyRef)thisScope).CopyVersionInfoToMSCorLib();
  494. // thisScope = MSCorLib.mscorlib;
  495. //}
  496. tables[(int)MDTable.Assembly][0] = thisScope;
  497. }
  498. else
  499. {
  500. Assembly.Read(this, tables[(int)MDTable.Assembly], (PEFile)thisScope);
  501. ((PEFile)thisScope).SetThisAssembly((Assembly)tables[(int)MDTable.Assembly][0]);
  502. }
  503. }
  504. }
  505. /// <summary>
  506. /// Read the Module metadata for this PE file.
  507. /// If reading refs only, then thisModule is the ModuleRef
  508. /// If reading defs then pefile is the Module
  509. /// </summary>
  510. /* private void GetThisPEFileScope() {
  511. if (refsOnly) {
  512. thisModuleRef = Module.ReadModuleRef(this);
  513. } else {
  514. pefile.Read(this);
  515. tables[(int)MDTable.Module][0] = pefile;
  516. }
  517. }
  518. private AssemblyRef GetThisAssembly(bool atPos) {
  519. if (tableLengths[(int)MDTable.Assembly] == 0) return null;
  520. if (!atPos)
  521. BaseStream.Position = tableStarts[(int)MDTable.Assembly];
  522. if (refsOnly)
  523. tables[(int)MDTable.Assembly][0] = Assembly.ReadAssemblyRef(this);
  524. else
  525. Assembly.Read(this,tables[(int)MDTable.Assembly],pefile);
  526. return (AssemblyRef)tables[(int)MDTable.Assembly][0];
  527. }
  528. */
  529. /*
  530. private ReferenceScope ReadRefsOnDemand() {
  531. ModuleRef thisModule;
  532. SetUpTableInfo();
  533. ResolutionScope mod;
  534. AssemblyRef thisAssembly = GetThisAssemblyRef();
  535. SetElementPosition(MDTable.Module,0);
  536. ReadZeros(2);
  537. name = buff.GetString();
  538. mvid = buff.GetGUID();
  539. ModuleRef thisMod = ModuleRef.GetModuleRef(name);
  540. if (thisMod == null) {
  541. thisMod = new ModuleRef(name);
  542. Module.AddToList(thisMod);
  543. } else {
  544. }
  545. if (thisModule == null) {
  546. thisModule = new ModuleRef(name);
  547. thisModule.readAsDef = true;
  548. if (mod != null) ((Module)mod).refOf = thisModule;
  549. else Module.AddToList(thisModule);
  550. } else {
  551. if (thisModule.readAsDef) return thisModule;
  552. return Merge(thisModule);
  553. }
  554. ReferenceScope thisScope = thisAssembly;
  555. if (thisScope == null) thisScope = thisModule;
  556. ClassRef defClass = ReadDefaultClass();
  557. thisScope.SetDefaultClass(defClass);
  558. ClassDef.GetClassRefNames(this,thisScope);
  559. return null;
  560. }
  561. */
  562. private void ReadMetaDataTableRefs()
  563. {
  564. SetUpTableInfo();
  565. SetThisScope();
  566. // ReadAssemblyRefs
  567. SetElementPosition(MDTable.AssemblyRef, 1);
  568. if (tableLengths[(int)MDTable.AssemblyRef] > 0)
  569. AssemblyRef.Read(this, tables[(int)MDTable.AssemblyRef]);
  570. // Read File Table (for ModuleRefs)
  571. //SetElementPosition(MDTable.File,1);
  572. if (tableLengths[(int)MDTable.File] > 0)
  573. FileRef.Read(this, tables[(int)MDTable.File]);
  574. // Read Exported Classes
  575. //SetElementPosition(MDTable.ExportedType,1);
  576. if (tableLengths[(int)MDTable.ExportedType] > 0)
  577. ExternClass.GetClassRefs(this, tables[(int)MDTable.ExportedType]);
  578. // Read ModuleRefs
  579. if (tableLengths[(int)MDTable.ModuleRef] > 0)
  580. {
  581. BaseStream.Position = tableStarts[(int)MDTable.ModuleRef];
  582. ModuleRef.Read(this, tables[(int)MDTable.ModuleRef], true);
  583. }
  584. uint[] parIxs = new uint[tableLengths[(int)MDTable.TypeDef]];
  585. BaseStream.Position = tableStarts[(int)MDTable.NestedClass];
  586. MapElem.ReadNestedClassInfo(this, tableLengths[(int)MDTable.NestedClass], parIxs);
  587. BaseStream.Position = tableStarts[(int)MDTable.TypeRef];
  588. // Read ClassRefs
  589. if (tableLengths[(int)MDTable.TypeRef] > 0)
  590. ClassRef.Read(this, tables[(int)MDTable.TypeRef], true);
  591. // Read ClassDefs and fields and methods
  592. ClassDef.GetClassRefs(this, tables[(int)MDTable.TypeDef], (ReferenceScope)thisScope, parIxs);
  593. for (int i = 0; i < tableLengths[(int)MDTable.ExportedType]; i++)
  594. {
  595. ((ClassRef)tables[(int)MDTable.ExportedType][i]).ResolveParent(this, true);
  596. }
  597. }
  598. internal void SetElementPosition(MDTable tabIx, uint ix)
  599. {
  600. BaseStream.Position = tableStarts[(int)tabIx] + (md.elemSize[(int)tabIx] * (ix - 1));
  601. }
  602. internal void ReadMethodImpls(ClassDef theClass, uint classIx)
  603. {
  604. SetElementPosition(MDTable.InterfaceImpl, 0);
  605. for (int i = 0; (i < tableLengths[(int)MDTable.MethodImpl]); i++)
  606. {
  607. uint clIx = GetIndex(MDTable.TypeDef);
  608. uint bodIx = GetCodedIndex(CIx.MethodDefOrRef);
  609. uint declIx = GetCodedIndex(CIx.MethodDefOrRef);
  610. if (clIx == classIx)
  611. {
  612. MethodImpl mImpl = new MethodImpl(this, theClass, bodIx, declIx);
  613. theClass.AddMethodImpl(mImpl);
  614. tables[(int)MDTable.MethodImpl][i] = mImpl;
  615. }
  616. }
  617. }
  618. internal void InsertInTable(MDTable tabIx, uint ix, MetaDataElement elem)
  619. {
  620. tables[(int)tabIx][ix - 1] = elem;
  621. }
  622. private void CheckForRefMerges()
  623. {
  624. if (tableLengths[(int)MDTable.TypeRef] > 0)
  625. {
  626. for (int i = 0; i < tableLengths[(int)MDTable.TypeRef]; i++)
  627. {
  628. ((ClassRef)tables[(int)MDTable.TypeRef][i]).ResolveParent(this, false);
  629. }
  630. }
  631. if (tableLengths[(int)MDTable.MemberRef] > 0)
  632. {
  633. for (int i = 0; i < tableLengths[(int)MDTable.MemberRef]; i++)
  634. {
  635. Member memb = (Member)tables[(int)MDTable.MemberRef][i];
  636. tables[(int)MDTable.MemberRef][i] = memb.ResolveParent(this);
  637. }
  638. }
  639. }
  640. internal void ReplaceSig(Signature sig, Type sigType)
  641. {
  642. tables[(int)MDTable.StandAloneSig][sig.Row - 1] = sigType;
  643. }
  644. internal void GetGenericParams(MethodDef meth)
  645. {
  646. if (tables[(int)MDTable.GenericParam] != null)
  647. {
  648. for (int j = 0; j < tables[(int)MDTable.GenericParam].Length; j++)
  649. {
  650. ((GenericParam)tables[(int)MDTable.GenericParam][j]).CheckParent(meth, this);
  651. }
  652. }
  653. }
  654. private void ReadMetaDataTables()
  655. {
  656. ((PEFile)thisScope).Read(this);
  657. tables[(int)MDTable.Module][0] = thisScope;
  658. for (int ix = 1; ix < MetaData.NumMetaDataTables; ix++)
  659. {
  660. if (tableLengths[ix] > 0)
  661. {
  662. switch (ix)
  663. {
  664. case ((int)MDTable.Assembly):
  665. Assembly.Read(this, tables[ix], (PEFile)thisScope);
  666. break;
  667. case ((int)MDTable.AssemblyOS):
  668. case ((int)MDTable.AssemblyProcessor):
  669. case ((int)MDTable.AssemblyRefOS):
  670. case ((int)MDTable.AssemblyRefProcessor):
  671. // ignore
  672. Console.WriteLine("Got uncompressed table " + (MDTable)ix);
  673. BaseStream.Seek(tableLengths[ix] * md.elemSize[ix], SeekOrigin.Current);
  674. break;
  675. case ((int)MDTable.AssemblyRef):
  676. AssemblyRef.Read(this, tables[ix]); break;
  677. //case 0x25 : AssemblyRefOS.Read(this,tables[ix]); break;
  678. //case 0x24 : AssemblyRefProcessor.Read(this,tables[ix]); break;
  679. case ((int)MDTable.ClassLayout):
  680. ClassLayout.Read(this, tables[ix]); break;
  681. case ((int)MDTable.Constant):
  682. ConstantElem.Read(this, tables[ix]); break;
  683. case ((int)MDTable.CustomAttribute):
  684. CustomAttribute.Read(this, tables[ix]); break;
  685. case ((int)MDTable.DeclSecurity):
  686. DeclSecurity.Read(this, tables[ix]); break;
  687. case ((int)MDTable.Event):
  688. Event.Read(this, tables[ix]); break;
  689. case ((int)MDTable.EventMap):
  690. MapElem.Read(this, tables[ix], MDTable.EventMap); break;
  691. case ((int)MDTable.ExportedType):
  692. ExternClass.Read(this, tables[ix]); break;
  693. case ((int)MDTable.Field):
  694. FieldDef.Read(this, tables[ix]); break;
  695. case ((int)MDTable.FieldLayout):
  696. FieldLayout.Read(this, tables[ix]); break;
  697. case ((int)MDTable.FieldMarshal):
  698. FieldMarshal.Read(this, tables[ix]); break;
  699. case ((int)MDTable.FieldRVA):
  700. FieldRVA.Read(this, tables[ix]); break;
  701. case ((int)MDTable.File):
  702. FileRef.Read(this, tables[ix]); break;
  703. case ((int)MDTable.GenericParam):
  704. GenericParam.Read(this, tables[ix]); break;
  705. case ((int)MDTable.GenericParamConstraint):
  706. GenericParamConstraint.Read(this, tables[ix]); break;
  707. case ((int)MDTable.ImplMap):
  708. ImplMap.Read(this, tables[ix]); break;
  709. case ((int)MDTable.InterfaceImpl):
  710. InterfaceImpl.Read(this, tables[ix]); break;
  711. case ((int)MDTable.ManifestResource):
  712. ManifestResource.Read(this, tables[ix]); break;
  713. case ((int)MDTable.MemberRef):
  714. Member.ReadMember(this, tables[ix]); break;
  715. case ((int)MDTable.Method):
  716. MethodDef.Read(this, tables[ix]); break;
  717. case ((int)MDTable.MethodImpl):
  718. MethodImpl.Read(this, tables[ix]); break;
  719. case ((int)MDTable.MethodSemantics):
  720. MethodSemantics.Read(this, tables[ix]); break;
  721. case ((int)MDTable.MethodSpec):
  722. MethodSpec.Read(this, tables[ix]); break;
  723. case ((int)MDTable.ModuleRef):
  724. ModuleRef.Read(this, tables[ix], false); break;
  725. case ((int)MDTable.NestedClass):
  726. MapElem.Read(this, tables[ix], MDTable.NestedClass);
  727. tables[ix] = null;
  728. break;
  729. case ((int)MDTable.Param):
  730. Param.Read(this, tables[ix]); break;
  731. case ((int)MDTable.Property):
  732. Property.Read(this, tables[ix]); break;
  733. case ((int)MDTable.PropertyMap):
  734. MapElem.Read(this, tables[ix], MDTable.PropertyMap); break;
  735. case ((int)MDTable.StandAloneSig):
  736. Signature.Read(this, tables[ix]); break;
  737. case ((int)MDTable.TypeDef):
  738. ClassDef.Read(this, tables[ix], ((PEFile)thisScope).isMSCorLib());
  739. break;
  740. case ((int)MDTable.TypeRef):
  741. ClassRef.Read(this, tables[ix], false); break;
  742. case ((int)MDTable.TypeSpec):
  743. TypeSpec.Read(this, tables[ix]); break;
  744. default: throw (new PEFileException("Unknown MetaData Table Type"));
  745. }
  746. }
  747. }
  748. CheckForRefMerges();
  749. for (int ix = 0; ix < MetaData.NumMetaDataTables; ix++)
  750. {
  751. if ((tables[ix] != null) && (ix != (int)MDTable.TypeSpec) &&
  752. (ix != (int)MDTable.MethodSpec))
  753. { // resolve type/method specs when referenced
  754. for (int j = 0; j < tables[ix].Length; j++)
  755. {
  756. //tables[ix][j].Row = (uint)j+1;
  757. // KJG fix 2005:02:23
  758. // Everett ILASM leaves gaps in table[10][x] ...
  759. // so protect with a null test.
  760. //
  761. // ((MetaDataElement)tables[ix][j]).Resolve(this); // old line ...
  762. //
  763. if (tables[ix][j] != null)
  764. {
  765. ((MetaDataElement)tables[ix][j]).Resolve(this);
  766. }
  767. }
  768. }
  769. }
  770. if (tableLengths[(int)MDTable.Assembly] > 0)
  771. ((PEFile)thisScope).SetThisAssembly((Assembly)tables[(int)MDTable.Assembly][0]);
  772. ((PEFile)thisScope).SetDefaultClass((ClassDef)tables[(int)MDTable.TypeDef][0]);
  773. for (int j = 1; j < tables[(int)MDTable.TypeDef].Length; j++)
  774. {
  775. ((PEFile)thisScope).AddToClassList((ClassDef)tables[(int)MDTable.TypeDef][j]);
  776. }
  777. if (tableLengths[(int)MDTable.ManifestResource] > 0)
  778. {
  779. for (int j = 0; j < tables[(int)MDTable.ManifestResource].Length; j++)
  780. {
  781. ((PEFile)thisScope).AddToResourceList((ManifestResource)tables[(int)MDTable.ManifestResource][j]);
  782. }
  783. }
  784. // We must protect the following code, since it seems possible
  785. // that "entryPoint" is a random value if isDLL is false,
  786. // leading to an index out of bounds error in some cases.
  787. if (!verInfo.isDLL && entryPoint != 0)
  788. {
  789. MetaDataElement ep = GetTokenElement(entryPoint);
  790. if (ep is MethodDef)
  791. ((MethodDef)ep).DeclareEntryPoint();
  792. else
  793. ((ModuleFile)ep).SetEntryPoint();
  794. }
  795. }
  796. internal uint GetIndex(MDTable tabIx)
  797. {
  798. if (md.largeIx[(int)tabIx]) return ReadUInt32();
  799. return ReadUInt16();
  800. }
  801. internal uint GetCodedIndex(CIx codedIx)
  802. {
  803. if (md.lgeCIx[(int)codedIx]) return ReadUInt32();
  804. return ReadUInt16();
  805. }
  806. internal uint GetTableSize(MDTable tabIx)
  807. {
  808. return (uint)tableLengths[(int)tabIx];
  809. }
  810. internal byte[] GetResource(uint offset)
  811. {
  812. BaseStream.Position = GetOffset(resourcesRVA) + offset;
  813. uint resSize = ReadUInt32();
  814. return ReadBytes((int)resSize);
  815. }
  816. internal MetaDataElement GetTokenElement(uint token)
  817. {
  818. uint tabIx = (token & FileImage.TableMask) >> 24;
  819. uint elemIx = (token & FileImage.ElementMask) - 1;
  820. MetaDataElement elem = (MetaDataElement)tables[tabIx][(int)elemIx];
  821. if ((elem != null) && (elem.unresolved))
  822. {
  823. elem.Resolve(this);
  824. elem = (MetaDataElement)tables[tabIx][(int)elemIx];
  825. }
  826. return elem;
  827. }
  828. internal MetaDataElement GetElement(MDTable tabIx, uint ix)
  829. {
  830. if (ix == 0) return null;
  831. MetaDataElement elem = (MetaDataElement)tables[(int)tabIx][(int)ix - 1];
  832. if ((elem != null) && (elem.unresolved))
  833. {
  834. elem.Resolve(this);
  835. elem = (MetaDataElement)tables[(int)tabIx][(int)ix - 1];
  836. }
  837. return elem;
  838. }
  839. internal MetaDataElement GetCodedElement(CIx code, uint ix)
  840. {
  841. uint mask = (uint)MetaData.CIxBitMasks[MetaData.CIxShiftMap[(uint)code]];
  842. int tabIx = MetaData.CIxTables[(int)code][(ix & mask)];
  843. ix >>= MetaData.CIxShiftMap[(uint)code];
  844. if (ix == 0) return null;
  845. MetaDataElement elem = (MetaDataElement)tables[tabIx][(int)ix - 1];
  846. if ((elem != null) && (elem.unresolved))
  847. {
  848. elem.Resolve(this);
  849. elem = (MetaDataElement)tables[tabIx][(int)ix - 1];
  850. }
  851. return elem;
  852. }
  853. internal uint MakeCodedIndex(CIx code, MDTable tab, uint ix)
  854. {
  855. ix <<= MetaData.CIxShiftMap[(uint)code];
  856. ix &= (uint)tab;
  857. return ix;
  858. }
  859. internal MDTable CodedTable(CIx code, uint ix)
  860. {
  861. uint mask = (uint)MetaData.CIxBitMasks[MetaData.CIxShiftMap[(uint)code]];
  862. return (MDTable)MetaData.CIxTables[(int)code][(ix & mask)];
  863. }
  864. internal uint CodedIndex(CIx code, uint ix)
  865. {
  866. ix >>= MetaData.CIxShiftMap[(uint)code];
  867. return ix;
  868. }
  869. internal byte[] GetBlob()
  870. {
  871. /* pre: buffer is at correct position to read blob index */
  872. uint ix;
  873. if (md.largeBlob) ix = ReadUInt32();
  874. else ix = ReadUInt16();
  875. return blob.GetBlob(ix);
  876. }
  877. internal byte[] GetBlob(uint ix)
  878. {
  879. return blob.GetBlob(ix);
  880. }
  881. internal uint GetBlobIx()
  882. {
  883. /* pre: buffer is at correct position to read blob index */
  884. //if (Diag.CADiag) Console.WriteLine("Getting blob index at " + BaseStream.Position);
  885. if (md.largeBlob) return ReadUInt32();
  886. return ReadUInt16();
  887. }
  888. internal byte FirstBlobByte(uint ix)
  889. {
  890. blob.GoToIndex(ix);
  891. uint blobSize = blob.ReadCompressedNum();
  892. return blob.ReadByte();
  893. }
  894. internal Constant GetBlobConst(int constType)
  895. {
  896. uint ix;
  897. if (md.largeBlob) ix = ReadUInt32();
  898. else ix = ReadUInt16();
  899. blob.GoToIndex(ix);
  900. uint blobSize = blob.ReadCompressedNum();
  901. if (constType == (int)ElementType.String)
  902. return new StringConst(blob.ReadBytes((int)blobSize));
  903. return ReadConst(constType, blob);
  904. }
  905. /*
  906. internal Constant ReadConstBlob(int constType, uint blobIx) {
  907. blob.GoToIndex(blobIx);
  908. Console.WriteLine("Reading constant blob at index " + blobIx );
  909. uint blobSize = blob.ReadCompressedNum();
  910. Console.WriteLine("Got constant blob size of " + blobSize);
  911. return ReadConst(constType);
  912. }
  913. */
  914. internal static Constant ReadConst(int constType, BinaryReader blob)
  915. {
  916. switch (constType)
  917. {
  918. case ((int)ElementType.Boolean):
  919. return new BoolConst(blob.ReadByte() != 0);
  920. case ((int)ElementType.Char):
  921. return new CharConst(blob.ReadChar());
  922. case ((int)ElementType.I1):
  923. return new IntConst(blob.ReadSByte());
  924. case ((int)ElementType.U1):
  925. return new UIntConst(blob.ReadByte());
  926. case ((int)ElementType.I2):
  927. return new IntConst(blob.ReadInt16());
  928. case ((int)ElementType.U2):
  929. return new UIntConst(blob.ReadUInt16());
  930. case ((int)ElementType.I4):
  931. return new IntConst(blob.ReadInt32());
  932. case ((int)ElementType.U4):
  933. return new UIntConst(blob.ReadUInt32());
  934. case ((int)ElementType.I8):
  935. return new IntConst(blob.ReadInt64());
  936. case ((int)ElementType.U8):
  937. return new UIntConst(blob.ReadUInt64());
  938. case ((int)ElementType.R4):
  939. return new FloatConst(blob.ReadSingle());
  940. case ((int)ElementType.R8):
  941. return new DoubleConst(blob.ReadDouble());
  942. case ((int)ElementType.ClassType):
  943. return new ClassTypeConst(blob.ReadString()); //GetBlobString());
  944. case ((int)ElementType.String):
  945. return new StringConst(blob.ReadString()); //GetBlobString());
  946. case ((int)ElementType.Class):
  947. return new ClassTypeConst(blob.ReadString()); //GetBlobString());
  948. //uint junk = blob.ReadUInt32(); // need to read name??
  949. //return new NullRefConst();
  950. case ((int)ElementType.ValueType): // only const value type is enum??
  951. return new IntConst(blob.ReadInt32());
  952. default: return null;
  953. }
  954. }
  955. internal string GetBlobString()
  956. {
  957. uint ix;
  958. if (md.largeBlob) ix = ReadUInt32();
  959. else ix = ReadUInt16();
  960. return blob.GetBlobString(ix);
  961. }
  962. internal string GetString()
  963. {
  964. uint ix;
  965. if (md.largeStrings) ix = ReadUInt32();
  966. else ix = ReadUInt16();
  967. return strings.GetString(ix);
  968. }
  969. internal string GetString(uint ix)
  970. {
  971. return strings.GetString(ix);
  972. }
  973. internal uint GetStringIx()
  974. {
  975. if (md.largeStrings) return ReadUInt32();
  976. else return ReadUInt16();
  977. }
  978. internal uint GetGUIDIx()
  979. {
  980. /* pre: buffer is at correct position to read GUID index */
  981. if (md.largeGUID) return ReadUInt32();
  982. return ReadUInt16();
  983. }
  984. public Guid GetGUID()
  985. {
  986. uint ix;
  987. if (md.largeGUID) ix = ReadUInt32();
  988. else ix = ReadUInt16();
  989. return new Guid(guid.GetBlob(((ix - 1) * 16), 16));
  990. }
  991. public string GetUserString()
  992. {
  993. uint ix;
  994. if (md.largeUS) ix = ReadUInt32();
  995. else ix = ReadUInt16();
  996. return userstring.GetUserString(ix);
  997. }
  998. internal bool IsFieldSig(uint blobIx)
  999. {
  1000. blob.GoToIndex(blobIx);
  1001. uint blobSize = blob.ReadCompressedNum();
  1002. byte fldByte = blob.ReadByte();
  1003. return fldByte == Field.FieldTag;
  1004. }
  1005. internal MethSig ReadMethSig(Method thisMeth, uint blobIx)
  1006. {
  1007. blob.GoToIndex(blobIx);
  1008. uint blobSize = blob.ReadCompressedNum();
  1009. return ReadMethSig(thisMeth, false);
  1010. }
  1011. internal MethSig ReadMethSig(Method thisMeth, string name, uint blobIx)
  1012. {
  1013. blob.GoToIndex(blobIx);
  1014. uint blobSize = blob.ReadCompressedNum();
  1015. MethSig mSig = ReadMethSig(thisMeth, false);
  1016. mSig.name = name;
  1017. return mSig;
  1018. }
  1019. private MethSig ReadMethSig(Method currMeth, bool firstByteRead)
  1020. {
  1021. MethSig meth = new MethSig(null);
  1022. if (!firstByteRead)
  1023. {
  1024. byte firstByte = blob.ReadByte();
  1025. if (firstByte == Field.FieldTag)
  1026. return null;
  1027. meth.callConv = (CallConv)firstByte;
  1028. }
  1029. if ((meth.callConv & CallConv.Generic) != 0)
  1030. {
  1031. meth.numGenPars = blob.ReadCompressedNum();
  1032. if (currMeth is MethodRef)
  1033. {
  1034. ((MethodRef)currMeth).MakeGenericPars(meth.numGenPars);
  1035. }
  1036. }
  1037. uint parCount = blob.ReadCompressedNum();
  1038. if (Diag.DiagOn) Console.WriteLine("Method sig has " + parCount + " parameters");
  1039. meth.retType = GetBlobType();//currClass,currMeth);
  1040. if (meth.retType == null)
  1041. System.Diagnostics.Debug.Assert(meth.retType != null);
  1042. int optParStart = -1;
  1043. ArrayList pTypes = new ArrayList();
  1044. for (int i = 0; i < parCount; i++)
  1045. {
  1046. Type pType = GetBlobType();//currClass,currMeth);
  1047. if (pType == sentinel)
  1048. {
  1049. optParStart = i;
  1050. pType = GetBlobType();//currClass,currMeth);
  1051. }
  1052. if (Diag.DiagOn) if (pType == null) Console.WriteLine("Param type is null");
  1053. pTypes.Add(pType);
  1054. }
  1055. if (optParStart > -1)
  1056. {
  1057. meth.numPars = (uint)optParStart;
  1058. meth.numOptPars = parCount - meth.numPars;
  1059. meth.optParTypes = new Type[meth.numOptPars];
  1060. for (int i = 0; i < meth.numOptPars; i++)
  1061. {
  1062. meth.optParTypes[i] = (Type)pTypes[i + optParStart];
  1063. }
  1064. }
  1065. else
  1066. meth.numPars = parCount;
  1067. meth.parTypes = new Type[meth.numPars];
  1068. for (int i = 0; i < meth.numPars; i++)
  1069. {
  1070. meth.parTypes[i] = (Type)pTypes[i];
  1071. }
  1072. return meth;
  1073. }
  1074. internal Type[] ReadMethSpecSig(uint blobIx)
  1075. { //ClassDef currClass, Method currMeth, uint blobIx) {
  1076. blob.GoToIndex(blobIx);
  1077. uint blobSize = blob.ReadCompressedNum();
  1078. if (blob.ReadByte() != MethodSpec.GENERICINST)
  1079. throw new Exception("Not a MethodSpec signature");
  1080. return GetListOfType(); //currClass,currMeth);
  1081. }
  1082. internal Type GetFieldType(uint blobIx)
  1083. {
  1084. //Console.WriteLine("Getting field type");
  1085. blob.GoToIndex(blobIx);
  1086. uint blobSize = blob.ReadCompressedNum();
  1087. byte fldByte = blob.ReadByte();
  1088. if (fldByte != 0x6)
  1089. throw new Exception("Expected field signature");
  1090. //if ((currClass != null) && (currClass is ClassRef))
  1091. // currClass = null;
  1092. return GetBlobType(); //currClass,null);
  1093. }
  1094. internal Type GetBlobType(uint blobIx)
  1095. { //Class currClass, Method currMeth, uint blobIx) {
  1096. blob.GoToIndex(blobIx);
  1097. uint blobSize = blob.ReadCompressedNum();
  1098. return GetBlobType(); //currClass,currMeth);
  1099. }
  1100. private Type[] GetListOfType()
  1101. { //Class currClass | Method currMeth) {
  1102. uint numPars = blob.ReadCompressedNum();
  1103. Type[] gPars = new Type[numPars];
  1104. for (int i = 0; i < numPars; i++)
  1105. {
  1106. gPars[i] = GetBlobType(); //currClass|currMeth);
  1107. }
  1108. return gPars;
  1109. }
  1110. private Type GetBlobType()
  1111. { //Class currClass, Method currMeth) {
  1112. byte typeIx = blob.ReadByte();
  1113. if (Diag.DiagOn) Console.WriteLine("Getting blob type " + (ElementType)typeIx);
  1114. if (typeIx < PrimitiveType.primitives.Length)
  1115. return PrimitiveType.primitives[typeIx];
  1116. switch (typeIx)
  1117. {
  1118. case ((int)ElementType.Ptr):
  1119. return new UnmanagedPointer(GetBlobType()); //currClass,currMeth));
  1120. case ((int)ElementType.ByRef):
  1121. return new ManagedPointer(GetBlobType()); //currClass,currMeth));
  1122. case ((int)ElementType.ValueType):
  1123. //Console.WriteLine("Reading value type");
  1124. uint vcIx = blob.ReadCompressedNum();
  1125. Class vClass = (Class)GetCodedElement(CIx.TypeDefOrRef, vcIx);
  1126. vClass.MakeValueClass();
  1127. return vClass;
  1128. case ((int)ElementType.Class):
  1129. return (Class)GetCodedElement(CIx.TypeDefOrRef, blob.ReadCompressedNum());
  1130. case ((int)ElementType.Array):
  1131. Type elemType = GetBlobType(); //currClass,currMeth);
  1132. int rank = (int)blob.ReadCompressedNum();
  1133. int numSizes = (int)blob.ReadCompressedNum();
  1134. int[] sizes = null;
  1135. int[] hiBounds = null;
  1136. if (numSizes > 0)
  1137. {
  1138. sizes = new int[numSizes];
  1139. hiBounds = new int[numSizes];
  1140. for (int i = 0; i < numSizes; i++)
  1141. sizes[i] = (int)blob.ReadCompressedNum();
  1142. }
  1143. int numLoBounds = (int)blob.ReadCompressedNum();
  1144. int[] loBounds = null;
  1145. //
  1146. // We have the constraints:
  1147. // 0 <= numSizes <= numLoBounds <= rank
  1148. //
  1149. if (numLoBounds > 0)
  1150. {
  1151. int constraint = (numLoBounds < numSizes ? numSizes : numLoBounds);
  1152. loBounds = new int[constraint];
  1153. //loBounds = new int[numLoBounds];
  1154. for (int i = 0; i < numLoBounds; i++)
  1155. loBounds[i] = blob.ReadCompressedInt();
  1156. if (numSizes > 0)
  1157. for (int i = 0; i < numSizes; i++)
  1158. hiBounds[i] = loBounds[i] + sizes[i] - 1;
  1159. }
  1160. if (numLoBounds == 0) // Implies numSizes == 0 also
  1161. return new BoundArray(elemType, rank);
  1162. else
  1163. return new BoundArray(elemType, rank, loBounds, hiBounds);
  1164. case ((int)ElementType.TypedByRef):
  1165. return PrimitiveType.TypedRef;
  1166. case ((int)ElementType.I):
  1167. return PrimitiveType.IntPtr;
  1168. case ((int)ElementType.U):
  1169. return PrimitiveType.UIntPtr;
  1170. case ((int)ElementType.FnPtr):
  1171. MethSig mSig = ReadMethSig(null, false);
  1172. return new MethPtrType(mSig);
  1173. case ((int)ElementType.Object):
  1174. return PrimitiveType.Object;
  1175. case ((int)ElementType.SZArray):
  1176. return new ZeroBasedArray(GetBlobType()); //currClass,currMeth));
  1177. case ((int)ElementType.CmodReqd):
  1178. case ((int)ElementType.CmodOpt):
  1179. Class modType = (Class)GetCodedElement(CIx.TypeDefOrRef, blob.ReadCompressedNum());
  1180. return new CustomModifiedType(GetBlobType(), (CustomModifier)typeIx, modType);
  1181. case ((int)ElementType.Sentinel):
  1182. return sentinel;
  1183. case ((int)ElementType.Pinned):
  1184. return pinned;
  1185. case ((int)ElementType.GenericInst):
  1186. Class instType = (Class)GetBlobType();
  1187. Class scopeSave = currentClassScope;
  1188. if (genInstNestLevel > 0)
  1189. {
  1190. currentClassScope = instType;
  1191. }
  1192. genInstNestLevel++;
  1193. ClassSpec newClassSpec = new ClassSpec(instType, GetListOfType());
  1194. genInstNestLevel--;
  1195. if (genInstNestLevel > 0)
  1196. {
  1197. currentClassScope = scopeSave;
  1198. }
  1199. return newClassSpec;
  1200. case ((int)ElementType.Var):
  1201. if (currentClassScope == null)
  1202. {
  1203. //Console.WriteLine("GenericParam with currClass == null");
  1204. return GenericParam.AnonClassPar(blob.ReadCompressedNum());
  1205. //throw new Exception("No current class set");
  1206. }
  1207. return currentClassScope.GetGenPar(blob.ReadCompressedNum());
  1208. case ((int)ElementType.MVar):
  1209. if (currentMethodScope == null)
  1210. {
  1211. //Console.WriteLine("GenericParam with currMeth == null");
  1212. return GenericParam.AnonMethPar(blob.ReadCompressedNum());
  1213. //throw new Exception("No current method set");
  1214. }
  1215. return currentMethodScope.GetGenericParam((int)blob.ReadCompressedNum());
  1216. default: break;
  1217. }
  1218. return null;
  1219. }
  1220. internal NativeType GetBlobNativeType(uint blobIx)
  1221. {
  1222. blob.GoToIndex(blobIx);
  1223. uint blobSize = blob.ReadCompressedNum();
  1224. return GetBlobNativeType();
  1225. }
  1226. internal NativeType GetBlobNativeType()
  1227. {
  1228. byte typeIx = blob.ReadByte();
  1229. if (typeIx == (byte)NativeTypeIx.Array)
  1230. {
  1231. return new NativeArray(GetBlobNativeType(), blob.ReadCompressedNum(),
  1232. blob.ReadCompressedNum(), blob.ReadCompressedNum());
  1233. }
  1234. else
  1235. return NativeType.GetNativeType(typeIx);
  1236. }
  1237. internal Local[] ReadLocalSig(uint sigIx)
  1238. { //Class currClass, Method currMeth, uint sigIx) {
  1239. blob.GoToIndex(sigIx);
  1240. uint blobSize = blob.ReadCompressedNum();
  1241. if (blob.ReadByte() != LocalSig.LocalSigByte) InputError();
  1242. uint count = blob.ReadCompressedNum();
  1243. Local[] locals = new Local[count];
  1244. for (uint i = 0; i < count; i++)
  1245. {
  1246. Type lType = GetBlobType(); //currClass,currMeth);
  1247. bool pinnedLocal = lType == pinned;
  1248. if (pinnedLocal) lType = GetBlobType(); //currClass,currMeth);
  1249. locals[i] = new Local("loc" + i, lType, pinnedLocal);
  1250. }
  1251. return locals;
  1252. }
  1253. internal void ReadPropertySig(uint sigIx, Property prop)
  1254. {
  1255. blob.GoToIndex(sigIx);
  1256. uint blobSize = blob.ReadCompressedNum();
  1257. if ((blob.ReadByte() & Property.PropertyTag) != Property.PropertyTag) InputError();
  1258. uint count = blob.ReadCompressedNum();
  1259. Type[] pars = new Type[count];
  1260. prop.SetPropertyType(GetBlobType()); //prop.GetParent(),null));
  1261. for (int i = 0; i < count; i++)
  1262. pars[i] = GetBlobType(); //prop.GetParent(),null);
  1263. prop.SetPropertyParams(pars);
  1264. }
  1265. internal DataConstant GetDataConstant(uint rva, Type constType) {
  1266. ManagedPointer pointer = null;
  1267. ClassDef image = null;
  1268. BaseStream.Seek(GetOffset(rva), SeekOrigin.Begin);
  1269. if (constType is PrimitiveType) {
  1270. switch (constType.GetTypeIndex()) {
  1271. case ((int)ElementType.I1): return new IntConst(ReadByte());
  1272. case ((int)ElementType.I2): return new IntConst(ReadInt16());
  1273. case ((int)ElementType.I4): return new IntConst(ReadInt32());
  1274. case ((int)ElementType.I8): return new IntConst(ReadInt64());
  1275. case ((int)ElementType.R4): return new FloatConst(ReadSingle());
  1276. case ((int)ElementType.R8): return new DoubleConst(ReadDouble());
  1277. case ((int)ElementType.String): return new StringConst(ReadString());
  1278. }
  1279. }
  1280. else if ((pointer = constType as ManagedPointer) != null) {
  1281. uint dataRVA = ReadUInt32();
  1282. Type baseType = pointer.GetBaseType();
  1283. return new AddressConstant(GetDataConstant(dataRVA, baseType));
  1284. } // need to do repeated constant??
  1285. else if ((image = constType as ClassDef) != null && image.Layout != null) {
  1286. byte[] data = new byte[image.Layout.GetSize()];
  1287. for (int i = 0; i < data.Length; i++)
  1288. data[i] = ReadByte();
  1289. return new ByteArrConst(data);
  1290. }
  1291. return null;
  1292. }
  1293. internal ModuleFile GetFileDesc(string name)
  1294. {
  1295. if (tables[(int)MDTable.File] == null) return null;
  1296. for (int i = 0; i < tables[(int)MDTable.File].Length; i++)
  1297. {
  1298. FileRef fr = (FileRef)tables[(int)MDTable.File][i];
  1299. if (fr.Name() == name)
  1300. {
  1301. if (fr is ModuleFile) return (ModuleFile)fr;
  1302. fr = new ModuleFile(fr.Name(), fr.GetHash());
  1303. tables[(int)MDTable.File][i] = fr;
  1304. return (ModuleFile)fr;
  1305. }
  1306. }
  1307. return null;
  1308. }
  1309. /*
  1310. private long GetOffset(int rva) {
  1311. for (int i=0; i < inputSections.Length; i++) {
  1312. long offs = inputSections[i].GetOffset(rva);
  1313. if (offs > 0) return offs;
  1314. }
  1315. return 0;
  1316. }
  1317. public bool ReadPadding(int boundary) {
  1318. while ((Position % boundary) != 0) {
  1319. if (buffer[index++] != 0) { return false; }
  1320. }
  1321. return true;
  1322. }
  1323. public String ReadName() {
  1324. int len = NAMELEN;
  1325. char [] nameStr = new char[NAMELEN];
  1326. char ch = (char)ReadByte();
  1327. int i=0;
  1328. for (; (i < NAMELEN) && (ch != '\0'); i++) {
  1329. nameStr[i] = ch;
  1330. ch = (char)ReadByte();
  1331. }
  1332. return new String(nameStr,0,i);
  1333. }
  1334. internal String ReadString() {
  1335. char [] str = new char[STRLEN];
  1336. int i=0;
  1337. char ch = (char)ReadByte();
  1338. for (; ch != '\0'; i++) {
  1339. str[i] = ch;
  1340. ch = (char)ReadByte();
  1341. }
  1342. return new String(str,0,i);
  1343. }
  1344. public long GetPos() {
  1345. return BaseStream.Position;
  1346. }
  1347. public void SetPos(int ix) {
  1348. BaseStream.Position = ix;
  1349. }
  1350. */
  1351. /*
  1352. public void SetToRVA(int rva) {
  1353. index = PESection.GetOffset(rva);
  1354. // Console.WriteLine("Setting buffer to rva " + PEConsts.Hex(rva) + " = index " + PEConsts.Hex(index));
  1355. // Console.WriteLine("Setting buffer to rva " + rva + " = index " + index);
  1356. }
  1357. public byte[] GetBuffer() {
  1358. return buffer;
  1359. }
  1360. */
  1361. private CILInstruction[] DoByteCodes(uint len, MethodDef thisMeth)
  1362. {
  1363. uint pos = 0;
  1364. ArrayList instrList = new ArrayList();
  1365. //int instrIx = 0;
  1366. while (pos < len)
  1367. {
  1368. uint offset = pos;
  1369. uint opCode = ReadByte();
  1370. pos++;
  1371. IType iType = IType.op;
  1372. if (opCode == 0xFE)
  1373. {
  1374. uint ix = ReadByte();
  1375. pos++;
  1376. opCode = (opCode << 8) + ix;
  1377. iType = FileImage.longInstrMap[ix];
  1378. }
  1379. else
  1380. iType = FileImage.instrMap[opCode];
  1381. if (Diag.DiagOn) Console.WriteLine("Got instruction type " + iType);
  1382. CILInstruction nextInstr = null;
  1383. if (iType == IType.specialOp)
  1384. {
  1385. pos += 4;
  1386. if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode));
  1387. switch (opCode)
  1388. {
  1389. case ((int)SpecialOp.ldc_i8):
  1390. nextInstr = new LongInstr((SpecialOp)opCode, ReadInt64());
  1391. pos += 4; break;
  1392. case ((int)SpecialOp.ldc_r4):
  1393. nextInstr = new FloatInstr((SpecialOp)opCode, ReadSingle());
  1394. break;
  1395. case ((int)SpecialOp.ldc_r8):
  1396. nextInstr = new DoubleInstr((SpecialOp)opCode, ReadDouble());
  1397. pos += 4; break;
  1398. case ((int)SpecialOp.calli):
  1399. nextInstr = new SigInstr((SpecialOp)opCode, (CalliSig)GetTokenElement(ReadUInt32()));
  1400. break;
  1401. case ((int)SpecialOp.Switch): // switch
  1402. uint count = ReadUInt32();
  1403. int[] offsets = new int[count];
  1404. for (uint i = 0; i < count; i++)
  1405. offsets[i] = ReadInt32();
  1406. pos += (4 * count);
  1407. nextInstr = new SwitchInstr(offsets);
  1408. break;
  1409. case ((int)SpecialOp.ldstr): // ldstr
  1410. uint strIx = ReadUInt32();
  1411. strIx = strIx & FileImage.ElementMask;
  1412. nextInstr = new StringInstr((SpecialOp)opCode, userstring.GetUserString(strIx));
  1413. break;
  1414. case ((int)MethodOp.ldtoken):
  1415. MetaDataElement elem = GetTokenElement(ReadUInt32());
  1416. if (elem is Method)
  1417. nextInstr = new MethInstr((MethodOp)opCode, (Method)elem);
  1418. else if (elem is Field)
  1419. nextInstr = new FieldInstr((FieldOp)opCode, (Field)elem);
  1420. else
  1421. nextInstr = new TypeInstr((TypeOp)opCode, (Type)elem);
  1422. break;
  1423. }
  1424. }
  1425. else if (iType == IType.branchOp)
  1426. {
  1427. if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode));
  1428. if ((opCode < 0x38) || (opCode == 0xDE))
  1429. { // br or leave.s
  1430. nextInstr = new BranchInstr(opCode, ReadSByte());
  1431. pos++;
  1432. }
  1433. else
  1434. {
  1435. nextInstr = new BranchInstr(opCode, ReadInt32());
  1436. pos += 4;
  1437. }
  1438. }
  1439. else
  1440. {
  1441. if (Diag.DiagOn) Console.Write(Hex.Byte((int)opCode));
  1442. switch (iType)
  1443. {
  1444. case (IType.op):
  1445. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (Op)opCode);
  1446. nextInstr = new Instr((Op)opCode); break;
  1447. case (IType.methOp):
  1448. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (MethodOp)opCode);
  1449. nextInstr = new MethInstr((MethodOp)opCode, (Method)GetTokenElement(ReadUInt32()));
  1450. pos += 4;
  1451. break;
  1452. case (IType.typeOp):
  1453. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (TypeOp)opCode);
  1454. uint ttok = ReadUInt32();
  1455. Type typeToken = (Type)GetTokenElement(ttok);
  1456. if (typeToken is GenericParTypeSpec)
  1457. typeToken = ((GenericParTypeSpec)typeToken).GetGenericParam(thisMeth);
  1458. nextInstr = new TypeInstr((TypeOp)opCode, typeToken);
  1459. pos += 4;
  1460. break;
  1461. case (IType.fieldOp):
  1462. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (FieldOp)opCode);
  1463. nextInstr = new FieldInstr((FieldOp)opCode, (Field)GetTokenElement(ReadUInt32()));
  1464. pos += 4;
  1465. break;
  1466. case (IType.int8Op):
  1467. nextInstr = new IntInstr((IntOp)opCode, ReadSByte());
  1468. pos++;
  1469. break;
  1470. case (IType.uint8Op):
  1471. nextInstr = new UIntInstr((IntOp)opCode, ReadByte());
  1472. pos++;
  1473. break;
  1474. case (IType.uint16Op):
  1475. nextInstr = new UIntInstr((IntOp)opCode, ReadUInt16());
  1476. pos++;
  1477. break;
  1478. case (IType.int32Op):
  1479. nextInstr = new IntInstr((IntOp)opCode, ReadInt32());
  1480. pos += 4;
  1481. break;
  1482. }
  1483. }
  1484. if (nextInstr != null) nextInstr.Resolve();
  1485. instrList.Add(nextInstr);
  1486. }
  1487. CILInstruction[] instrs = new CILInstruction[instrList.Count];
  1488. for (int i = 0; i < instrs.Length; i++)
  1489. {
  1490. instrs[i] = (CILInstruction)instrList[i];
  1491. }
  1492. return instrs;
  1493. }
  1494. public void ReadByteCodes(MethodDef meth, uint rva)
  1495. {
  1496. if (rva == 0) return;
  1497. BaseStream.Seek(GetOffset(rva), SeekOrigin.Begin);
  1498. CILInstructions instrs = meth.CreateCodeBuffer();
  1499. uint formatByte = ReadByte();
  1500. uint format = formatByte & 0x3;
  1501. if (Diag.DiagOn) Console.WriteLine("code header format = " + Hex.Byte((int)formatByte));
  1502. uint size = 0;
  1503. if (format == CILInstructions.TinyFormat)
  1504. {
  1505. size = formatByte >> 2;
  1506. if (Diag.DiagOn) Console.WriteLine("Tiny Format, code size = " + size);
  1507. instrs.SetAndResolveInstructions(DoByteCodes(size, meth));
  1508. }
  1509. else if (format == CILInstructions.FatFormat)
  1510. {
  1511. uint headerSize = ReadByte();
  1512. bool initLocals = (formatByte & CILInstructions.InitLocals) != 0;
  1513. bool moreSects = (formatByte & CILInstructions.MoreSects) != 0;
  1514. meth.SetMaxStack((int)ReadUInt16());
  1515. size = ReadUInt32();
  1516. if (Diag.DiagOn) Console.WriteLine("Fat Format, code size = " + size);
  1517. uint locVarSig = ReadUInt32();
  1518. CILInstruction[] instrList = this.DoByteCodes(size, meth);
  1519. while (moreSects)
  1520. {
  1521. // find next 4 byte boundary
  1522. long currPos = BaseStream.Position;
  1523. if (currPos % 4 != 0)
  1524. {
  1525. long pad = 4 - (currPos % 4);
  1526. for (int p = 0; p < pad; p++)
  1527. ReadByte();
  1528. }
  1529. uint flags = ReadByte();
  1530. //while (flags == 0) flags = ReadByte(); // maximum of 3 to get 4 byte boundary??
  1531. moreSects = (flags & CILInstructions.SectMoreSects) != 0;
  1532. bool fatSect = (flags & CILInstructions.SectFatFormat) != 0;
  1533. if ((flags & CILInstructions.EHTable) == 0)
  1534. throw new Exception("Section not an Exception Handler Table");
  1535. int sectLen = ReadByte() + (ReadByte() << 8) + (ReadByte() << 16);
  1536. int numClauses = sectLen - 4;
  1537. if (fatSect)
  1538. numClauses /= 24;
  1539. else
  1540. numClauses /= 12;
  1541. for (int i = 0; i < numClauses; i++)
  1542. {
  1543. EHClauseType eFlag;
  1544. if (fatSect) eFlag = (EHClauseType)ReadUInt32();
  1545. else eFlag = (EHClauseType)ReadUInt16();
  1546. uint tryOff = 0, tryLen = 0, hOff = 0, hLen = 0;
  1547. if (fatSect)
  1548. {
  1549. tryOff = ReadUInt32();
  1550. tryLen = ReadUInt32();
  1551. hOff = ReadUInt32();
  1552. hLen = ReadUInt32();
  1553. }
  1554. else
  1555. {
  1556. tryOff = ReadUInt16();
  1557. tryLen = ReadByte();
  1558. hOff = ReadUInt16();
  1559. hLen = ReadByte();
  1560. }
  1561. EHClause ehClause = new EHClause(eFlag, tryOff, tryLen, hOff, hLen);
  1562. if (eFlag == EHClauseType.Exception)
  1563. ehClause.ClassToken(GetTokenElement(ReadUInt32()));
  1564. else
  1565. ehClause.FilterOffset(ReadUInt32());
  1566. instrs.AddEHClause(ehClause);
  1567. }
  1568. }
  1569. if (locVarSig != 0)
  1570. {
  1571. LocalSig lSig = (LocalSig)GetTokenElement(locVarSig);
  1572. lSig.Resolve(this, meth);
  1573. meth.AddLocals(lSig.GetLocals(), initLocals);
  1574. }
  1575. instrs.SetAndResolveInstructions(instrList);
  1576. }
  1577. else
  1578. {
  1579. Console.WriteLine("byte code format error");
  1580. }
  1581. }
  1582. }
  1583. }