PEReader.cs 73 KB

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