PEReader.cs 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679
  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. else
  768. {
  769. Console.WriteLine();
  770. }
  771. }
  772. }
  773. }
  774. if (tableLengths[(int)MDTable.Assembly] > 0)
  775. ((PEFile)thisScope).SetThisAssembly((Assembly)tables[(int)MDTable.Assembly][0]);
  776. ((PEFile)thisScope).SetDefaultClass((ClassDef)tables[(int)MDTable.TypeDef][0]);
  777. for (int j = 1; j < tables[(int)MDTable.TypeDef].Length; j++)
  778. {
  779. ((PEFile)thisScope).AddToClassList((ClassDef)tables[(int)MDTable.TypeDef][j]);
  780. }
  781. if (tableLengths[(int)MDTable.ManifestResource] > 0)
  782. {
  783. for (int j = 0; j < tables[(int)MDTable.ManifestResource].Length; j++)
  784. {
  785. ((PEFile)thisScope).AddToResourceList((ManifestResource)tables[(int)MDTable.ManifestResource][j]);
  786. }
  787. }
  788. // We must protect the following code, since it seems possible
  789. // that "entryPoint" is a random value if isDLL is false,
  790. // leading to an index out of bounds error in some cases.
  791. if (!verInfo.isDLL && entryPoint != 0)
  792. {
  793. MetaDataElement ep = GetTokenElement(entryPoint);
  794. if (ep is MethodDef)
  795. ((MethodDef)ep).DeclareEntryPoint();
  796. else
  797. ((ModuleFile)ep).SetEntryPoint();
  798. }
  799. }
  800. internal uint GetIndex(MDTable tabIx)
  801. {
  802. if (md.largeIx[(int)tabIx]) return ReadUInt32();
  803. return ReadUInt16();
  804. }
  805. internal uint GetCodedIndex(CIx codedIx)
  806. {
  807. if (md.lgeCIx[(int)codedIx]) return ReadUInt32();
  808. return ReadUInt16();
  809. }
  810. internal uint GetTableSize(MDTable tabIx)
  811. {
  812. return (uint)tableLengths[(int)tabIx];
  813. }
  814. internal byte[] GetResource(uint offset)
  815. {
  816. BaseStream.Position = GetOffset(resourcesRVA) + offset;
  817. uint resSize = ReadUInt32();
  818. return ReadBytes((int)resSize);
  819. }
  820. internal MetaDataElement GetTokenElement(uint token)
  821. {
  822. uint tabIx = (token & FileImage.TableMask) >> 24;
  823. uint elemIx = (token & FileImage.ElementMask) - 1;
  824. MetaDataElement elem = (MetaDataElement)tables[tabIx][(int)elemIx];
  825. if ((elem != null) && (elem.unresolved))
  826. {
  827. elem.Resolve(this);
  828. elem = (MetaDataElement)tables[tabIx][(int)elemIx];
  829. }
  830. return elem;
  831. }
  832. internal MetaDataElement GetElement(MDTable tabIx, uint ix)
  833. {
  834. if (ix == 0) return null;
  835. MetaDataElement elem = (MetaDataElement)tables[(int)tabIx][(int)ix - 1];
  836. if ((elem != null) && (elem.unresolved))
  837. {
  838. elem.Resolve(this);
  839. elem = (MetaDataElement)tables[(int)tabIx][(int)ix - 1];
  840. }
  841. return elem;
  842. }
  843. internal MetaDataElement GetCodedElement(CIx code, uint ix)
  844. {
  845. uint mask = (uint)MetaData.CIxBitMasks[MetaData.CIxShiftMap[(uint)code]];
  846. int tabIx = MetaData.CIxTables[(int)code][(ix & mask)];
  847. ix >>= MetaData.CIxShiftMap[(uint)code];
  848. if (ix == 0) return null;
  849. MetaDataElement elem = (MetaDataElement)tables[tabIx][(int)ix - 1];
  850. if ((elem != null) && (elem.unresolved))
  851. {
  852. elem.Resolve(this);
  853. elem = (MetaDataElement)tables[tabIx][(int)ix - 1];
  854. }
  855. return elem;
  856. }
  857. internal uint MakeCodedIndex(CIx code, MDTable tab, uint ix)
  858. {
  859. ix <<= MetaData.CIxShiftMap[(uint)code];
  860. ix &= (uint)tab;
  861. return ix;
  862. }
  863. internal MDTable CodedTable(CIx code, uint ix)
  864. {
  865. uint mask = (uint)MetaData.CIxBitMasks[MetaData.CIxShiftMap[(uint)code]];
  866. return (MDTable)MetaData.CIxTables[(int)code][(ix & mask)];
  867. }
  868. internal uint CodedIndex(CIx code, uint ix)
  869. {
  870. ix >>= MetaData.CIxShiftMap[(uint)code];
  871. return ix;
  872. }
  873. internal byte[] GetBlob()
  874. {
  875. /* pre: buffer is at correct position to read blob index */
  876. uint ix;
  877. if (md.largeBlob) ix = ReadUInt32();
  878. else ix = ReadUInt16();
  879. return blob.GetBlob(ix);
  880. }
  881. internal byte[] GetBlob(uint ix)
  882. {
  883. return blob.GetBlob(ix);
  884. }
  885. internal uint GetBlobIx()
  886. {
  887. /* pre: buffer is at correct position to read blob index */
  888. //if (Diag.CADiag) Console.WriteLine("Getting blob index at " + BaseStream.Position);
  889. if (md.largeBlob) return ReadUInt32();
  890. return ReadUInt16();
  891. }
  892. internal byte FirstBlobByte(uint ix)
  893. {
  894. blob.GoToIndex(ix);
  895. uint blobSize = blob.ReadCompressedNum();
  896. return blob.ReadByte();
  897. }
  898. internal Constant GetBlobConst(int constType)
  899. {
  900. uint ix;
  901. if (md.largeBlob) ix = ReadUInt32();
  902. else ix = ReadUInt16();
  903. blob.GoToIndex(ix);
  904. uint blobSize = blob.ReadCompressedNum();
  905. if (constType == (int)ElementType.String)
  906. return new StringConst(blob.ReadBytes((int)blobSize));
  907. return ReadConst(constType, blob);
  908. }
  909. /*
  910. internal Constant ReadConstBlob(int constType, uint blobIx) {
  911. blob.GoToIndex(blobIx);
  912. Console.WriteLine("Reading constant blob at index " + blobIx );
  913. uint blobSize = blob.ReadCompressedNum();
  914. Console.WriteLine("Got constant blob size of " + blobSize);
  915. return ReadConst(constType);
  916. }
  917. */
  918. internal static Constant ReadConst(int constType, BinaryReader blob)
  919. {
  920. switch (constType)
  921. {
  922. case ((int)ElementType.Boolean):
  923. return new BoolConst(blob.ReadByte() != 0);
  924. case ((int)ElementType.Char):
  925. return new CharConst(blob.ReadChar());
  926. case ((int)ElementType.I1):
  927. return new IntConst(blob.ReadSByte());
  928. case ((int)ElementType.U1):
  929. return new UIntConst(blob.ReadByte());
  930. case ((int)ElementType.I2):
  931. return new IntConst(blob.ReadInt16());
  932. case ((int)ElementType.U2):
  933. return new UIntConst(blob.ReadUInt16());
  934. case ((int)ElementType.I4):
  935. return new IntConst(blob.ReadInt32());
  936. case ((int)ElementType.U4):
  937. return new UIntConst(blob.ReadUInt32());
  938. case ((int)ElementType.I8):
  939. return new IntConst(blob.ReadInt64());
  940. case ((int)ElementType.U8):
  941. return new UIntConst(blob.ReadUInt64());
  942. case ((int)ElementType.R4):
  943. return new FloatConst(blob.ReadSingle());
  944. case ((int)ElementType.R8):
  945. return new DoubleConst(blob.ReadDouble());
  946. case ((int)ElementType.ClassType):
  947. return new ClassTypeConst(blob.ReadString()); //GetBlobString());
  948. case ((int)ElementType.String):
  949. return new StringConst(blob.ReadString()); //GetBlobString());
  950. case ((int)ElementType.Class):
  951. return new ClassTypeConst(blob.ReadString()); //GetBlobString());
  952. //uint junk = blob.ReadUInt32(); // need to read name??
  953. //return new NullRefConst();
  954. case ((int)ElementType.ValueType): // only const value type is enum??
  955. return new IntConst(blob.ReadInt32());
  956. default: return null;
  957. }
  958. }
  959. internal string GetBlobString()
  960. {
  961. uint ix;
  962. if (md.largeBlob) ix = ReadUInt32();
  963. else ix = ReadUInt16();
  964. return blob.GetBlobString(ix);
  965. }
  966. internal string GetString()
  967. {
  968. uint ix;
  969. if (md.largeStrings) ix = ReadUInt32();
  970. else ix = ReadUInt16();
  971. return strings.GetString(ix);
  972. }
  973. internal string GetString(uint ix)
  974. {
  975. return strings.GetString(ix);
  976. }
  977. internal uint GetStringIx()
  978. {
  979. if (md.largeStrings) return ReadUInt32();
  980. else return ReadUInt16();
  981. }
  982. internal uint GetGUIDIx()
  983. {
  984. /* pre: buffer is at correct position to read GUID index */
  985. if (md.largeGUID) return ReadUInt32();
  986. return ReadUInt16();
  987. }
  988. public Guid GetGUID()
  989. {
  990. uint ix;
  991. if (md.largeGUID) ix = ReadUInt32();
  992. else ix = ReadUInt16();
  993. return new Guid(guid.GetBlob(((ix - 1) * 16), 16));
  994. }
  995. public string GetUserString()
  996. {
  997. uint ix;
  998. if (md.largeUS) ix = ReadUInt32();
  999. else ix = ReadUInt16();
  1000. return userstring.GetUserString(ix);
  1001. }
  1002. internal bool IsFieldSig(uint blobIx)
  1003. {
  1004. blob.GoToIndex(blobIx);
  1005. uint blobSize = blob.ReadCompressedNum();
  1006. byte fldByte = blob.ReadByte();
  1007. return fldByte == Field.FieldTag;
  1008. }
  1009. internal MethSig ReadMethSig(Method thisMeth, uint blobIx)
  1010. {
  1011. blob.GoToIndex(blobIx);
  1012. uint blobSize = blob.ReadCompressedNum();
  1013. return ReadMethSig(thisMeth, false);
  1014. }
  1015. internal MethSig ReadMethSig(Method thisMeth, string name, uint blobIx)
  1016. {
  1017. blob.GoToIndex(blobIx);
  1018. uint blobSize = blob.ReadCompressedNum();
  1019. MethSig mSig = ReadMethSig(thisMeth, false);
  1020. mSig.name = name;
  1021. return mSig;
  1022. }
  1023. private MethSig ReadMethSig(Method currMeth, bool firstByteRead)
  1024. {
  1025. //Class currClass = null;
  1026. //if (currMeth != null) currClass = (Class)currMeth.GetParent();
  1027. MethSig meth = new MethSig(null);
  1028. if (!firstByteRead)
  1029. {
  1030. byte firstByte = blob.ReadByte();
  1031. if (firstByte == Field.FieldTag)
  1032. return null;
  1033. meth.callConv = (CallConv)firstByte;
  1034. }
  1035. if ((meth.callConv & CallConv.Generic) != 0)
  1036. {
  1037. meth.numGenPars = blob.ReadCompressedNum();
  1038. if (currMeth is MethodRef)
  1039. {
  1040. ((MethodRef)currMeth).MakeGenericPars(meth.numGenPars);
  1041. } //else if (currMeth is MethodDef) {
  1042. //GetGenericParams((MethodDef)currMeth);
  1043. //}
  1044. }
  1045. uint parCount = blob.ReadCompressedNum();
  1046. if (Diag.DiagOn) Console.WriteLine("Method sig has " + parCount + " parameters");
  1047. meth.retType = GetBlobType();//currClass,currMeth);
  1048. if (meth.retType == null)
  1049. System.Diagnostics.Debug.Assert(meth.retType != null);
  1050. int optParStart = -1;
  1051. ArrayList pTypes = new ArrayList();
  1052. for (int i = 0; i < parCount; i++)
  1053. {
  1054. Type pType = GetBlobType();//currClass,currMeth);
  1055. if (pType == sentinel)
  1056. {
  1057. optParStart = i;
  1058. pType = GetBlobType();//currClass,currMeth);
  1059. }
  1060. if (Diag.DiagOn) if (pType == null) Console.WriteLine("Param type is null");
  1061. pTypes.Add(pType);
  1062. }
  1063. if (optParStart > -1)
  1064. {
  1065. meth.numPars = (uint)optParStart;
  1066. meth.numOptPars = parCount - meth.numPars;
  1067. meth.optParTypes = new Type[meth.numOptPars];
  1068. for (int i = 0; i < meth.numOptPars; i++)
  1069. {
  1070. meth.optParTypes[i] = (Type)pTypes[i + optParStart];
  1071. }
  1072. }
  1073. else
  1074. meth.numPars = parCount;
  1075. meth.parTypes = new Type[meth.numPars];
  1076. for (int i = 0; i < meth.numPars; i++)
  1077. {
  1078. meth.parTypes[i] = (Type)pTypes[i];
  1079. }
  1080. return meth;
  1081. }
  1082. internal Type[] ReadMethSpecSig(uint blobIx)
  1083. { //ClassDef currClass, Method currMeth, uint blobIx) {
  1084. blob.GoToIndex(blobIx);
  1085. uint blobSize = blob.ReadCompressedNum();
  1086. if (blob.ReadByte() != MethodSpec.GENERICINST)
  1087. throw new Exception("Not a MethodSpec signature");
  1088. return GetListOfType(); //currClass,currMeth);
  1089. }
  1090. internal Type GetFieldType(uint blobIx)
  1091. {
  1092. //Console.WriteLine("Getting field type");
  1093. blob.GoToIndex(blobIx);
  1094. uint blobSize = blob.ReadCompressedNum();
  1095. byte fldByte = blob.ReadByte();
  1096. if (fldByte != 0x6)
  1097. throw new Exception("Expected field signature");
  1098. //if ((currClass != null) && (currClass is ClassRef))
  1099. // currClass = null;
  1100. return GetBlobType(); //currClass,null);
  1101. }
  1102. internal Type GetBlobType(uint blobIx)
  1103. { //Class currClass, Method currMeth, uint blobIx) {
  1104. blob.GoToIndex(blobIx);
  1105. uint blobSize = blob.ReadCompressedNum();
  1106. return GetBlobType(); //currClass,currMeth);
  1107. }
  1108. private Type[] GetListOfType()
  1109. { //Class currClass, Method currMeth) {
  1110. uint numPars = blob.ReadCompressedNum();
  1111. Type[] gPars = new Type[numPars];
  1112. for (int i = 0; i < numPars; i++)
  1113. {
  1114. gPars[i] = GetBlobType(); //currClass,currMeth);
  1115. }
  1116. return gPars;
  1117. }
  1118. private Type GetBlobType()
  1119. { //Class currClass, Method currMeth) {
  1120. byte typeIx = blob.ReadByte();
  1121. if (Diag.DiagOn) Console.WriteLine("Getting blob type " + (ElementType)typeIx);
  1122. if (typeIx < PrimitiveType.primitives.Length)
  1123. return PrimitiveType.primitives[typeIx];
  1124. switch (typeIx)
  1125. {
  1126. case ((int)ElementType.Ptr):
  1127. return new UnmanagedPointer(GetBlobType()); //currClass,currMeth));
  1128. case ((int)ElementType.ByRef):
  1129. return new ManagedPointer(GetBlobType()); //currClass,currMeth));
  1130. case ((int)ElementType.ValueType):
  1131. //Console.WriteLine("Reading value type");
  1132. uint vcIx = blob.ReadCompressedNum();
  1133. Class vClass = (Class)GetCodedElement(CIx.TypeDefOrRef, vcIx);
  1134. vClass.MakeValueClass();
  1135. return vClass;
  1136. case ((int)ElementType.Class):
  1137. return (Class)GetCodedElement(CIx.TypeDefOrRef, blob.ReadCompressedNum());
  1138. case ((int)ElementType.Array):
  1139. Type elemType = GetBlobType(); //currClass,currMeth);
  1140. int rank = (int)blob.ReadCompressedNum();
  1141. int numSizes = (int)blob.ReadCompressedNum();
  1142. int[] sizes = null;
  1143. int[] hiBounds = null;
  1144. if (numSizes > 0)
  1145. {
  1146. sizes = new int[numSizes];
  1147. hiBounds = new int[numSizes];
  1148. for (int i = 0; i < numSizes; i++)
  1149. sizes[i] = (int)blob.ReadCompressedNum();
  1150. }
  1151. int numLoBounds = (int)blob.ReadCompressedNum();
  1152. int[] loBounds = null;
  1153. //
  1154. // We have the constraints:
  1155. // 0 <= numSizes <= numLoBounds <= rank
  1156. //
  1157. if (numLoBounds > 0)
  1158. {
  1159. loBounds = new int[numLoBounds];
  1160. for (int i = 0; i < numLoBounds; i++)
  1161. loBounds[i] = blob.ReadCompressedInt();
  1162. if (numSizes > 0)
  1163. for (int i = 0; i < numSizes; i++)
  1164. hiBounds[i] = loBounds[i] + sizes[i] - 1;
  1165. }
  1166. if (numLoBounds == 0) // Implies numSizes == 0 also
  1167. return new BoundArray(elemType, rank);
  1168. else
  1169. return new BoundArray(elemType, rank, loBounds, hiBounds);
  1170. case ((int)ElementType.TypedByRef):
  1171. return PrimitiveType.TypedRef;
  1172. case ((int)ElementType.I):
  1173. return PrimitiveType.IntPtr;
  1174. case ((int)ElementType.U):
  1175. return PrimitiveType.UIntPtr;
  1176. case ((int)ElementType.FnPtr):
  1177. MethSig mSig = ReadMethSig(null, false);
  1178. return new MethPtrType(mSig);
  1179. case ((int)ElementType.Object):
  1180. return PrimitiveType.Object;
  1181. case ((int)ElementType.SZArray):
  1182. return new ZeroBasedArray(GetBlobType()); //currClass,currMeth));
  1183. case ((int)ElementType.CmodReqd):
  1184. case ((int)ElementType.CmodOpt):
  1185. Class modType = (Class)GetCodedElement(CIx.TypeDefOrRef, blob.ReadCompressedNum());
  1186. return new CustomModifiedType(GetBlobType(), (CustomModifier)typeIx, modType);
  1187. case ((int)ElementType.Sentinel):
  1188. return sentinel;
  1189. case ((int)ElementType.Pinned):
  1190. return pinned;
  1191. case ((int)ElementType.GenericInst):
  1192. Class instType = (Class)GetBlobType();
  1193. Class scopeSave = currentClassScope;
  1194. if (genInstNestLevel > 0)
  1195. {
  1196. currentClassScope = instType;
  1197. }
  1198. genInstNestLevel++;
  1199. ClassSpec newClassSpec = new ClassSpec(instType, GetListOfType());
  1200. genInstNestLevel--;
  1201. if (genInstNestLevel > 0)
  1202. {
  1203. currentClassScope = scopeSave;
  1204. }
  1205. return newClassSpec;
  1206. case ((int)ElementType.Var):
  1207. if (currentClassScope == null)
  1208. {
  1209. //Console.WriteLine("GenericParam with currClass == null");
  1210. return GenericParam.AnonClassPar(blob.ReadCompressedNum());
  1211. //throw new Exception("No current class set");
  1212. }
  1213. return currentClassScope.GetGenPar(blob.ReadCompressedNum());
  1214. case ((int)ElementType.MVar):
  1215. if (currentMethodScope == null)
  1216. {
  1217. //Console.WriteLine("GenericParam with currMeth == null");
  1218. return GenericParam.AnonMethPar(blob.ReadCompressedNum());
  1219. //throw new Exception("No current method set");
  1220. }
  1221. return currentMethodScope.GetGenericParam((int)blob.ReadCompressedNum());
  1222. default: break;
  1223. }
  1224. return null;
  1225. }
  1226. internal NativeType GetBlobNativeType(uint blobIx)
  1227. {
  1228. blob.GoToIndex(blobIx);
  1229. uint blobSize = blob.ReadCompressedNum();
  1230. return GetBlobNativeType();
  1231. }
  1232. internal NativeType GetBlobNativeType()
  1233. {
  1234. byte typeIx = blob.ReadByte();
  1235. if (typeIx == (byte)NativeTypeIx.Array)
  1236. {
  1237. return new NativeArray(GetBlobNativeType(), blob.ReadCompressedNum(),
  1238. blob.ReadCompressedNum(), blob.ReadCompressedNum());
  1239. }
  1240. else
  1241. return NativeType.GetNativeType(typeIx);
  1242. }
  1243. internal Local[] ReadLocalSig(uint sigIx)
  1244. { //Class currClass, Method currMeth, uint sigIx) {
  1245. blob.GoToIndex(sigIx);
  1246. uint blobSize = blob.ReadCompressedNum();
  1247. if (blob.ReadByte() != LocalSig.LocalSigByte) InputError();
  1248. uint count = blob.ReadCompressedNum();
  1249. Local[] locals = new Local[count];
  1250. for (uint i = 0; i < count; i++)
  1251. {
  1252. Type lType = GetBlobType(); //currClass,currMeth);
  1253. bool pinnedLocal = lType == pinned;
  1254. if (pinnedLocal) lType = GetBlobType(); //currClass,currMeth);
  1255. locals[i] = new Local("loc" + i, lType, pinnedLocal);
  1256. }
  1257. return locals;
  1258. }
  1259. internal void ReadPropertySig(uint sigIx, Property prop)
  1260. {
  1261. blob.GoToIndex(sigIx);
  1262. uint blobSize = blob.ReadCompressedNum();
  1263. if ((blob.ReadByte() & Property.PropertyTag) != Property.PropertyTag) InputError();
  1264. uint count = blob.ReadCompressedNum();
  1265. Type[] pars = new Type[count];
  1266. prop.SetPropertyType(GetBlobType()); //prop.GetParent(),null));
  1267. for (int i = 0; i < count; i++)
  1268. pars[i] = GetBlobType(); //prop.GetParent(),null);
  1269. prop.SetPropertyParams(pars);
  1270. }
  1271. internal DataConstant GetDataConstant(uint rva, Type constType)
  1272. {
  1273. BaseStream.Seek(GetOffset(rva), SeekOrigin.Begin);
  1274. if (constType is PrimitiveType)
  1275. {
  1276. switch (constType.GetTypeIndex())
  1277. {
  1278. case ((int)ElementType.I1): return new IntConst(ReadByte());
  1279. case ((int)ElementType.I2): return new IntConst(ReadInt16());
  1280. case ((int)ElementType.I4): return new IntConst(ReadInt32());
  1281. case ((int)ElementType.I8): return new IntConst(ReadInt64());
  1282. case ((int)ElementType.R4): return new FloatConst(ReadSingle());
  1283. case ((int)ElementType.R8): return new DoubleConst(ReadDouble());
  1284. case ((int)ElementType.String): return new StringConst(ReadString());
  1285. }
  1286. }
  1287. else if (constType is ManagedPointer)
  1288. {
  1289. uint dataRVA = ReadUInt32();
  1290. Type baseType = ((ManagedPointer)constType).GetBaseType();
  1291. return new AddressConstant(GetDataConstant(dataRVA, baseType));
  1292. } // need to do repeated constant??
  1293. return null;
  1294. }
  1295. internal ModuleFile GetFileDesc(string name)
  1296. {
  1297. if (tables[(int)MDTable.File] == null) return null;
  1298. for (int i = 0; i < tables[(int)MDTable.File].Length; i++)
  1299. {
  1300. FileRef fr = (FileRef)tables[(int)MDTable.File][i];
  1301. if (fr.Name() == name)
  1302. {
  1303. if (fr is ModuleFile) return (ModuleFile)fr;
  1304. fr = new ModuleFile(fr.Name(), fr.GetHash());
  1305. tables[(int)MDTable.File][i] = fr;
  1306. return (ModuleFile)fr;
  1307. }
  1308. }
  1309. return null;
  1310. }
  1311. /*
  1312. private long GetOffset(int rva) {
  1313. for (int i=0; i < inputSections.Length; i++) {
  1314. long offs = inputSections[i].GetOffset(rva);
  1315. if (offs > 0) return offs;
  1316. }
  1317. return 0;
  1318. }
  1319. public bool ReadPadding(int boundary) {
  1320. while ((Position % boundary) != 0) {
  1321. if (buffer[index++] != 0) { return false; }
  1322. }
  1323. return true;
  1324. }
  1325. public String ReadName() {
  1326. int len = NAMELEN;
  1327. char [] nameStr = new char[NAMELEN];
  1328. char ch = (char)ReadByte();
  1329. int i=0;
  1330. for (; (i < NAMELEN) && (ch != '\0'); i++) {
  1331. nameStr[i] = ch;
  1332. ch = (char)ReadByte();
  1333. }
  1334. return new String(nameStr,0,i);
  1335. }
  1336. internal String ReadString() {
  1337. char [] str = new char[STRLEN];
  1338. int i=0;
  1339. char ch = (char)ReadByte();
  1340. for (; ch != '\0'; i++) {
  1341. str[i] = ch;
  1342. ch = (char)ReadByte();
  1343. }
  1344. return new String(str,0,i);
  1345. }
  1346. public long GetPos() {
  1347. return BaseStream.Position;
  1348. }
  1349. public void SetPos(int ix) {
  1350. BaseStream.Position = ix;
  1351. }
  1352. */
  1353. /*
  1354. public void SetToRVA(int rva) {
  1355. index = PESection.GetOffset(rva);
  1356. // Console.WriteLine("Setting buffer to rva " + PEConsts.Hex(rva) + " = index " + PEConsts.Hex(index));
  1357. // Console.WriteLine("Setting buffer to rva " + rva + " = index " + index);
  1358. }
  1359. public byte[] GetBuffer() {
  1360. return buffer;
  1361. }
  1362. */
  1363. private CILInstruction[] DoByteCodes(uint len, MethodDef thisMeth)
  1364. {
  1365. uint pos = 0;
  1366. ArrayList instrList = new ArrayList();
  1367. //int instrIx = 0;
  1368. while (pos < len)
  1369. {
  1370. uint offset = pos;
  1371. uint opCode = ReadByte();
  1372. pos++;
  1373. IType iType = IType.op;
  1374. if (opCode == 0xFE)
  1375. {
  1376. uint ix = ReadByte();
  1377. pos++;
  1378. opCode = (opCode << 8) + ix;
  1379. iType = FileImage.longInstrMap[ix];
  1380. }
  1381. else
  1382. iType = FileImage.instrMap[opCode];
  1383. if (Diag.DiagOn) Console.WriteLine("Got instruction type " + iType);
  1384. CILInstruction nextInstr = null;
  1385. if (iType == IType.specialOp)
  1386. {
  1387. pos += 4;
  1388. if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode));
  1389. switch (opCode)
  1390. {
  1391. case ((int)SpecialOp.ldc_i8):
  1392. nextInstr = new LongInstr((SpecialOp)opCode, ReadInt64());
  1393. pos += 4; break;
  1394. case ((int)SpecialOp.ldc_r4):
  1395. nextInstr = new FloatInstr((SpecialOp)opCode, ReadSingle());
  1396. break;
  1397. case ((int)SpecialOp.ldc_r8):
  1398. nextInstr = new DoubleInstr((SpecialOp)opCode, ReadDouble());
  1399. pos += 4; break;
  1400. case ((int)SpecialOp.calli):
  1401. nextInstr = new SigInstr((SpecialOp)opCode, (CalliSig)GetTokenElement(ReadUInt32()));
  1402. break;
  1403. case ((int)SpecialOp.Switch): // switch
  1404. uint count = ReadUInt32();
  1405. int[] offsets = new int[count];
  1406. for (uint i = 0; i < count; i++)
  1407. offsets[i] = ReadInt32();
  1408. pos += (4 * count);
  1409. nextInstr = new SwitchInstr(offsets);
  1410. break;
  1411. case ((int)SpecialOp.ldstr): // ldstr
  1412. uint strIx = ReadUInt32();
  1413. strIx = strIx & FileImage.ElementMask;
  1414. nextInstr = new StringInstr((SpecialOp)opCode, userstring.GetUserString(strIx));
  1415. break;
  1416. case ((int)MethodOp.ldtoken):
  1417. MetaDataElement elem = GetTokenElement(ReadUInt32());
  1418. if (elem is Method)
  1419. nextInstr = new MethInstr((MethodOp)opCode, (Method)elem);
  1420. else if (elem is Field)
  1421. nextInstr = new FieldInstr((FieldOp)opCode, (Field)elem);
  1422. else
  1423. nextInstr = new TypeInstr((TypeOp)opCode, (Type)elem);
  1424. break;
  1425. }
  1426. }
  1427. else if (iType == IType.branchOp)
  1428. {
  1429. if (Diag.DiagOn) Console.WriteLine("Got instruction " + Hex.Byte((int)opCode));
  1430. if ((opCode < 0x38) || (opCode == 0xDE))
  1431. { // br or leave.s
  1432. nextInstr = new BranchInstr(opCode, ReadSByte());
  1433. pos++;
  1434. }
  1435. else
  1436. {
  1437. nextInstr = new BranchInstr(opCode, ReadInt32());
  1438. pos += 4;
  1439. }
  1440. }
  1441. else
  1442. {
  1443. if (Diag.DiagOn) Console.Write(Hex.Byte((int)opCode));
  1444. switch (iType)
  1445. {
  1446. case (IType.op):
  1447. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (Op)opCode);
  1448. nextInstr = new Instr((Op)opCode); break;
  1449. case (IType.methOp):
  1450. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (MethodOp)opCode);
  1451. nextInstr = new MethInstr((MethodOp)opCode, (Method)GetTokenElement(ReadUInt32()));
  1452. pos += 4;
  1453. break;
  1454. case (IType.typeOp):
  1455. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (TypeOp)opCode);
  1456. uint ttok = ReadUInt32();
  1457. Type typeToken = (Type)GetTokenElement(ttok);
  1458. if (typeToken is GenericParTypeSpec)
  1459. typeToken = ((GenericParTypeSpec)typeToken).GetGenericParam(thisMeth);
  1460. nextInstr = new TypeInstr((TypeOp)opCode, typeToken);
  1461. pos += 4;
  1462. break;
  1463. case (IType.fieldOp):
  1464. if (Diag.DiagOn) Console.WriteLine("Got instruction " + (FieldOp)opCode);
  1465. nextInstr = new FieldInstr((FieldOp)opCode, (Field)GetTokenElement(ReadUInt32()));
  1466. pos += 4;
  1467. break;
  1468. case (IType.int8Op):
  1469. nextInstr = new IntInstr((IntOp)opCode, ReadSByte());
  1470. pos++;
  1471. break;
  1472. case (IType.uint8Op):
  1473. nextInstr = new UIntInstr((IntOp)opCode, ReadByte());
  1474. pos++;
  1475. break;
  1476. case (IType.uint16Op):
  1477. nextInstr = new UIntInstr((IntOp)opCode, ReadUInt16());
  1478. pos++;
  1479. break;
  1480. case (IType.int32Op):
  1481. nextInstr = new IntInstr((IntOp)opCode, ReadInt32());
  1482. pos += 4;
  1483. break;
  1484. }
  1485. }
  1486. if (nextInstr != null) nextInstr.Resolve();
  1487. instrList.Add(nextInstr);
  1488. }
  1489. CILInstruction[] instrs = new CILInstruction[instrList.Count];
  1490. for (int i = 0; i < instrs.Length; i++)
  1491. {
  1492. instrs[i] = (CILInstruction)instrList[i];
  1493. }
  1494. return instrs;
  1495. }
  1496. public void ReadByteCodes(MethodDef meth, uint rva)
  1497. {
  1498. if (rva == 0) return;
  1499. BaseStream.Seek(GetOffset(rva), SeekOrigin.Begin);
  1500. CILInstructions instrs = meth.CreateCodeBuffer();
  1501. uint formatByte = ReadByte();
  1502. uint format = formatByte & 0x3;
  1503. if (Diag.DiagOn) Console.WriteLine("code header format = " + Hex.Byte((int)formatByte));
  1504. uint size = 0;
  1505. if (format == CILInstructions.TinyFormat)
  1506. {
  1507. size = formatByte >> 2;
  1508. if (Diag.DiagOn) Console.WriteLine("Tiny Format, code size = " + size);
  1509. instrs.SetAndResolveInstructions(DoByteCodes(size, meth));
  1510. }
  1511. else if (format == CILInstructions.FatFormat)
  1512. {
  1513. uint headerSize = ReadByte();
  1514. bool initLocals = (formatByte & CILInstructions.InitLocals) != 0;
  1515. bool moreSects = (formatByte & CILInstructions.MoreSects) != 0;
  1516. meth.SetMaxStack((int)ReadUInt16());
  1517. size = ReadUInt32();
  1518. if (Diag.DiagOn) Console.WriteLine("Fat Format, code size = " + size);
  1519. uint locVarSig = ReadUInt32();
  1520. CILInstruction[] instrList = this.DoByteCodes(size, meth);
  1521. while (moreSects)
  1522. {
  1523. // find next 4 byte boundary
  1524. long currPos = BaseStream.Position;
  1525. if (currPos % 4 != 0)
  1526. {
  1527. long pad = 4 - (currPos % 4);
  1528. for (int p = 0; p < pad; p++)
  1529. ReadByte();
  1530. }
  1531. uint flags = ReadByte();
  1532. //while (flags == 0) flags = ReadByte(); // maximum of 3 to get 4 byte boundary??
  1533. moreSects = (flags & CILInstructions.SectMoreSects) != 0;
  1534. bool fatSect = (flags & CILInstructions.SectFatFormat) != 0;
  1535. if ((flags & CILInstructions.EHTable) == 0)
  1536. throw new Exception("Section not an Exception Handler Table");
  1537. int sectLen = ReadByte() + (ReadByte() << 8) + (ReadByte() << 16);
  1538. int numClauses = sectLen - 4;
  1539. if (fatSect)
  1540. numClauses /= 24;
  1541. else
  1542. numClauses /= 12;
  1543. for (int i = 0; i < numClauses; i++)
  1544. {
  1545. EHClauseType eFlag;
  1546. if (fatSect) eFlag = (EHClauseType)ReadUInt32();
  1547. else eFlag = (EHClauseType)ReadUInt16();
  1548. uint tryOff = 0, tryLen = 0, hOff = 0, hLen = 0;
  1549. if (fatSect)
  1550. {
  1551. tryOff = ReadUInt32();
  1552. tryLen = ReadUInt32();
  1553. hOff = ReadUInt32();
  1554. hLen = ReadUInt32();
  1555. }
  1556. else
  1557. {
  1558. tryOff = ReadUInt16();
  1559. tryLen = ReadByte();
  1560. hOff = ReadUInt16();
  1561. hLen = ReadByte();
  1562. }
  1563. EHClause ehClause = new EHClause(eFlag, tryOff, tryLen, hOff, hLen);
  1564. if (eFlag == EHClauseType.Exception)
  1565. ehClause.ClassToken(GetTokenElement(ReadUInt32()));
  1566. else
  1567. ehClause.FilterOffset(ReadUInt32());
  1568. instrs.AddEHClause(ehClause);
  1569. }
  1570. }
  1571. if (locVarSig != 0)
  1572. {
  1573. LocalSig lSig = (LocalSig)GetTokenElement(locVarSig);
  1574. lSig.Resolve(this, meth);
  1575. meth.AddLocals(lSig.GetLocals(), initLocals);
  1576. }
  1577. instrs.SetAndResolveInstructions(instrList);
  1578. }
  1579. else
  1580. {
  1581. Console.WriteLine("byte code format error");
  1582. }
  1583. }
  1584. }
  1585. }