PEAPI.cs 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195
  1. using System;
  2. using System.IO;
  3. using System.Collections;
  4. using System.Text;
  5. namespace PEAPI {
  6. /**************************************************************************/
  7. /// <summary>
  8. /// Image for a PEFile
  9. /// File Structure
  10. /// DOS Header (128 bytes)
  11. /// PE Signature ("PE\0\0")
  12. /// PEFileHeader (20 bytes)
  13. /// PEOptionalHeader (224 bytes)
  14. /// SectionHeaders (40 bytes * NumSections)
  15. ///
  16. /// Sections .text (always present - contains metadata)
  17. /// .sdata (contains any initialised data in the file - may not be present)
  18. /// (for ilams /debug this contains the Debug table)
  19. /// .reloc (always present - in pure CIL only has one fixup)
  20. /// others??? c# produces .rsrc section containing a Resource Table
  21. ///
  22. /// .text layout
  23. /// IAT (single entry 8 bytes for pure CIL)
  24. /// CLIHeader (72 bytes)
  25. /// CIL instructions for all methods (variable size)
  26. /// MetaData
  27. /// Root (20 bytes + UTF-8 Version String + quad align padding)
  28. /// StreamHeaders (8 bytes + null terminated name string + quad align padding)
  29. /// Streams
  30. /// #~ (always present - holds metadata tables)
  31. /// #Strings (always present - holds identifier strings)
  32. /// #US (Userstring heap)
  33. /// #Blob (signature blobs)
  34. /// #GUID (guids for assemblies or Modules)
  35. /// ImportTable (40 bytes)
  36. /// ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
  37. /// Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
  38. /// ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
  39. /// Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
  40. ///
  41. /// #~ stream structure
  42. /// Header (24 bytes)
  43. /// Rows (4 bytes * numTables)
  44. /// Tables
  45. /// </summary>
  46. internal class FileImage : BinaryWriter {
  47. internal readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
  48. internal readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
  49. 0x0000000000FF0000, 0x00000000FF000000,
  50. 0x000000FF00000000, 0x0000FF0000000000,
  51. 0x00FF000000000000, 0xFF00000000000000 };
  52. internal readonly static uint nibble0Mask = 0x0000000F;
  53. internal readonly static uint nibble1Mask = 0x000000F0;
  54. private static readonly byte[] DOSHeader = { 0x4d,0x5a,0x90,0x00,0x03,0x00,0x00,0x00,
  55. 0x04,0x00,0x00,0x00,0xff,0xff,0x00,0x00,
  56. 0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  57. 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  58. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  59. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  60. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  61. 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,
  62. 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,
  63. 0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
  64. 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,
  65. 0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
  66. 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,
  67. 0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
  68. 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,
  69. 0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  70. 0x50,0x45,0x00,0x00};
  71. private static byte[] PEHeader = { 0x4c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  73. 0xE0, 0x00, 0x0E, 0x01, // PE Header Standard Fields
  74. 0x0B, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
  75. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  76. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  77. };
  78. private static readonly uint minFileAlign = 0x200;
  79. private static readonly uint maxFileAlign = 0x1000;
  80. private static readonly uint fileHeaderSize = 0x178;
  81. private static readonly uint sectionHeaderSize = 40;
  82. private static readonly uint SectionAlignment = 0x2000;
  83. private static readonly uint ImageBase = 0x400000;
  84. private static readonly uint ImportTableSize = 40;
  85. private static readonly uint IATSize = 8;
  86. private static readonly uint CLIHeaderSize = 72;
  87. private uint runtimeFlags = 0x01; // COMIMAGE_FLAGS_ILONLY
  88. // 32BITREQUIRED 0x02, STRONGNAMESIGNED 0x08, TRACKDEBUGDATA 0x10000
  89. private static readonly uint StrongNameSignatureSize = 128;
  90. private bool reserveStrongNameSignatureSpace = false;
  91. private static readonly uint relocFlags = 0x42000040;
  92. private static readonly ushort exeCharacteristics = 0x010E;
  93. private static readonly ushort dllCharacteristics = 0x210E;
  94. // section names are all 8 bytes
  95. private static readonly string textName = ".text\0\0\0";
  96. private static readonly string sdataName = ".sdata\0\0";
  97. private static readonly string relocName = ".reloc\0\0";
  98. private static readonly string rsrcName = ".rsrc\0\0\0";
  99. private static readonly string exeHintNameTable = "\0\0_CorExeMain\0";
  100. private static readonly string dllHintNameTable = "\0\0_CorDllMain\0";
  101. private static readonly string runtimeEngineName = "mscoree.dll\0\0";
  102. private Section text, sdata, rsrc;
  103. ArrayList data;
  104. BinaryWriter reloc = new BinaryWriter(new MemoryStream());
  105. uint dateStamp = 0;
  106. DateTime origin = new DateTime(1970,1,1);
  107. uint numSections = 2; // always have .text and .reloc sections
  108. internal SubSystem subSys = SubSystem.Windows_CUI; // default is Windows Console mode
  109. internal long stackReserve = 0x100000; // default is 1Mb
  110. internal uint fileAlign = minFileAlign;
  111. uint entryPointOffset, entryPointPadding, imageSize, headerSize, headerPadding, entryPointToken = 0;
  112. uint relocOffset, relocRVA, relocSize, relocPadding, relocTide, hintNameTableOffset;
  113. uint metaDataOffset, runtimeEngineOffset, initDataSize = 0, importTablePadding;
  114. uint resourcesSize, resourcesOffset;
  115. uint strongNameSigOffset;
  116. uint importTableOffset, importLookupTableOffset, totalImportTableSize;
  117. MetaData metaData;
  118. char[] runtimeEngine = runtimeEngineName.ToCharArray(), hintNameTable;
  119. bool doDLL, largeStrings, largeGUID, largeUS, largeBlob;
  120. ushort characteristics;
  121. internal FileImage(bool makeDLL, string fileName) : base(new FileStream(fileName,FileMode.Create))
  122. {
  123. InitFileImage(makeDLL);
  124. TimeSpan tmp = System.IO.File.GetCreationTime(fileName).Subtract(origin);
  125. dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
  126. }
  127. internal FileImage(bool makeDLL, Stream str) : base(str)
  128. {
  129. InitFileImage(makeDLL);
  130. TimeSpan tmp = DateTime.Now.Subtract(origin);
  131. dateStamp = Convert.ToUInt32(tmp.TotalSeconds);
  132. }
  133. private void InitFileImage(bool makeDLL)
  134. {
  135. doDLL = makeDLL;
  136. if (doDLL) {
  137. hintNameTable = dllHintNameTable.ToCharArray();
  138. characteristics = dllCharacteristics;
  139. } else {
  140. hintNameTable = exeHintNameTable.ToCharArray();
  141. characteristics = exeCharacteristics;
  142. }
  143. text = new Section(textName,0x60000020); // IMAGE_SCN_CNT CODE, EXECUTE, READ
  144. // rsrc = new Section(rsrcName,0x40000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ
  145. metaData = new MetaData(this);
  146. }
  147. internal MetaData GetMetaData()
  148. {
  149. return metaData;
  150. }
  151. private uint GetNextSectStart(uint rva, uint tide)
  152. {
  153. if (tide < SectionAlignment) return rva + SectionAlignment;
  154. return rva + ((tide / SectionAlignment) + 1) * SectionAlignment;
  155. }
  156. private void BuildTextSection()
  157. {
  158. // .text layout
  159. // IAT (single entry 8 bytes for pure CIL)
  160. // CLIHeader (72 bytes)
  161. // CIL instructions for all methods (variable size)
  162. // MetaData
  163. // ImportTable (40 bytes)
  164. // ImportLookupTable(8 bytes) (same as IAT for standard CIL files)
  165. // Hint/Name Tables with entry "_CorExeMain" for .exe file and "_CorDllMain" for .dll (14 bytes)
  166. // ASCII string "mscoree.dll" referenced in ImportTable (+ padding = 16 bytes)
  167. // Entry Point (0xFF25 followed by 4 bytes 0x400000 + RVA of .text)
  168. metaData.BuildMetaData(IATSize + CLIHeaderSize);
  169. metaDataOffset = IATSize + CLIHeaderSize;
  170. // Console.WriteLine("Code starts at " + metaDataOffset);
  171. metaDataOffset += metaData.CodeSize();
  172. // resourcesStart =
  173. resourcesOffset = metaDataOffset + metaData.Size ();
  174. resourcesSize = metaData.GetResourcesSize ();
  175. if (reserveStrongNameSignatureSpace) {
  176. strongNameSigOffset = resourcesOffset + resourcesSize;
  177. // fixUps = RVA for vtable
  178. importTableOffset = strongNameSigOffset + StrongNameSignatureSize;
  179. } else {
  180. strongNameSigOffset = 0;
  181. // fixUps = RVA for vtable
  182. importTableOffset = resourcesOffset + resourcesSize;
  183. }
  184. importTablePadding = NumToAlign(importTableOffset,16);
  185. importTableOffset += importTablePadding;
  186. importLookupTableOffset = importTableOffset + ImportTableSize;
  187. hintNameTableOffset = importLookupTableOffset + IATSize;
  188. runtimeEngineOffset = hintNameTableOffset + (uint)hintNameTable.Length;
  189. entryPointOffset = runtimeEngineOffset + (uint)runtimeEngine.Length;
  190. totalImportTableSize = entryPointOffset - importTableOffset;
  191. // Console.WriteLine("total import table size = " + totalImportTableSize);
  192. // Console.WriteLine("entrypoint offset = " + entryPointOffset);
  193. entryPointPadding = NumToAlign(entryPointOffset,4) + 2;
  194. entryPointOffset += entryPointPadding;
  195. text.AddReloc(entryPointOffset+2);
  196. text.IncTide(entryPointOffset + 6);
  197. //if (text.Tide() < fileAlign) fileAlign = minFileAlign;
  198. text.SetSize(NumToAlign(text.Tide(),fileAlign));
  199. // Console.WriteLine("text size = " + text.Size() + " text tide = " + text.Tide() + " text padding = " + text.Padding());
  200. // Console.WriteLine("metaDataOffset = " + Hex.Int(metaDataOffset));
  201. // Console.WriteLine("importTableOffset = " + Hex.Int(importTableOffset));
  202. // Console.WriteLine("importLookupTableOffset = " + Hex.Int(importLookupTableOffset));
  203. // Console.WriteLine("hintNameTableOffset = " + Hex.Int(hintNameTableOffset));
  204. // Console.WriteLine("runtimeEngineOffset = " + Hex.Int(runtimeEngineOffset));
  205. // Console.WriteLine("entryPointOffset = " + Hex.Int(entryPointOffset));
  206. // Console.WriteLine("entryPointPadding = " + Hex.Int(entryPointPadding));
  207. }
  208. internal void BuildRelocSection()
  209. {
  210. text.DoRelocs(reloc);
  211. if (sdata != null) sdata.DoRelocs(reloc);
  212. if (rsrc != null) rsrc.DoRelocs(reloc);
  213. relocTide = (uint)reloc.Seek(0,SeekOrigin.Current);
  214. relocPadding = NumToAlign(relocTide,fileAlign);
  215. relocSize = relocTide + relocPadding;
  216. imageSize = relocRVA + SectionAlignment;
  217. initDataSize += relocSize;
  218. }
  219. private void CalcOffsets()
  220. {
  221. if (sdata != null)
  222. numSections++;
  223. if (rsrc != null)
  224. numSections++;
  225. headerSize = fileHeaderSize + (numSections * sectionHeaderSize);
  226. headerPadding = NumToAlign(headerSize,fileAlign);
  227. headerSize += headerPadding;
  228. uint offset = headerSize;
  229. uint rva = SectionAlignment;
  230. text.SetOffset(offset);
  231. text.SetRVA(rva);
  232. offset += text.Size();
  233. rva = GetNextSectStart(rva,text.Tide());
  234. // Console.WriteLine("headerSize = " + headerSize);
  235. // Console.WriteLine("headerPadding = " + headerPadding);
  236. // Console.WriteLine("textOffset = " + Hex.Int(text.Offset()));
  237. if (sdata != null) {
  238. sdata.SetSize(NumToAlign(sdata.Tide(),fileAlign));
  239. sdata.SetOffset(offset);
  240. sdata.SetRVA(rva);
  241. offset += sdata.Size();
  242. rva = GetNextSectStart(rva,sdata.Tide());
  243. initDataSize += sdata.Size();
  244. }
  245. if (rsrc != null) {
  246. rsrc.SetSize(NumToAlign(rsrc.Tide(),fileAlign));
  247. rsrc.SetOffset(offset);
  248. rsrc.SetRVA(rva);
  249. offset += rsrc.Size();
  250. rva = GetNextSectStart(rva,rsrc.Tide());
  251. initDataSize += rsrc.Size();
  252. }
  253. relocOffset = offset;
  254. relocRVA = rva;
  255. }
  256. internal void MakeFile()
  257. {
  258. if (doDLL) hintNameTable = dllHintNameTable.ToCharArray();
  259. else hintNameTable = exeHintNameTable.ToCharArray();
  260. BuildTextSection();
  261. CalcOffsets();
  262. BuildRelocSection();
  263. // now write it out
  264. WriteHeader();
  265. WriteSections();
  266. Flush();
  267. Close();
  268. }
  269. private void WriteHeader()
  270. {
  271. Write(DOSHeader);
  272. // Console.WriteLine("Writing PEHeader at offset " + Seek(0,SeekOrigin.Current));
  273. WritePEHeader();
  274. // Console.WriteLine("Writing text section header at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
  275. text.WriteHeader(this,relocRVA);
  276. if (sdata != null) sdata.WriteHeader(this,relocRVA);
  277. if (rsrc != null) rsrc.WriteHeader(this,relocRVA);
  278. // Console.WriteLine("Writing reloc section header at offset " + Seek(0,SeekOrigin.Current));
  279. WriteRelocSectionHeader();
  280. // Console.WriteLine("Writing padding at offset " + Seek(0,SeekOrigin.Current));
  281. WriteZeros(headerPadding);
  282. }
  283. private void WriteSections()
  284. {
  285. // Console.WriteLine("Writing text section at offset " + Seek(0,SeekOrigin.Current));
  286. WriteTextSection();
  287. if (sdata != null) WriteSDataSection();
  288. if (rsrc != null) WriteRsrcSection();
  289. WriteRelocSection();
  290. }
  291. private void WriteIAT()
  292. {
  293. Write(text.RVA() + hintNameTableOffset);
  294. Write(0);
  295. }
  296. private void WriteImportTables()
  297. {
  298. // Import Table
  299. WriteZeros(importTablePadding);
  300. // Console.WriteLine("Writing import tables at offset " + Hex.Long(Seek(0,SeekOrigin.Current)));
  301. Write(importLookupTableOffset + text.RVA());
  302. WriteZeros(8);
  303. Write(runtimeEngineOffset + text.RVA());
  304. Write(text.RVA()); // IAT is at the beginning of the text section
  305. WriteZeros(20);
  306. // Import Lookup Table
  307. WriteIAT(); // lookup table and IAT are the same
  308. // Hint/Name Table
  309. // Console.WriteLine("Writing hintname table at " + Hex.Long(Seek(0,SeekOrigin.Current)));
  310. Write(hintNameTable);
  311. Write(runtimeEngineName.ToCharArray());
  312. }
  313. private void WriteTextSection()
  314. {
  315. WriteIAT();
  316. WriteCLIHeader();
  317. // Console.WriteLine("Writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
  318. metaData.WriteByteCodes(this);
  319. // Console.WriteLine("Finished writing code at " + Hex.Long(Seek(0,SeekOrigin.Current)));
  320. largeStrings = metaData.LargeStringsIndex();
  321. largeGUID = metaData.LargeGUIDIndex();
  322. largeUS = metaData.LargeUSIndex();
  323. largeBlob = metaData.LargeBlobIndex();
  324. metaData.WriteMetaData(this);
  325. metaData.WriteResources (this);
  326. if (reserveStrongNameSignatureSpace) {
  327. WriteZeros(StrongNameSignatureSize);
  328. }
  329. WriteImportTables();
  330. WriteZeros(entryPointPadding);
  331. Write((ushort)0x25FF);
  332. Write(ImageBase + text.RVA());
  333. WriteZeros(text.Padding());
  334. }
  335. private void WriteCLIHeader()
  336. {
  337. Write(CLIHeaderSize); // Cb
  338. Write((short)2); // Major runtime version
  339. Write((short)0); // Minor runtime version
  340. Write(text.RVA() + metaDataOffset);
  341. Write(metaData.Size());
  342. Write(runtimeFlags);
  343. Write(entryPointToken);
  344. if (resourcesSize > 0) {
  345. Write (text.RVA () + resourcesOffset);
  346. Write (resourcesSize);
  347. } else {
  348. WriteZeros (8);
  349. }
  350. // Strong Name Signature (RVA, size)
  351. if (reserveStrongNameSignatureSpace) {
  352. Write(text.RVA() + strongNameSigOffset);
  353. Write(StrongNameSignatureSize);
  354. } else {
  355. WriteZeros(8);
  356. }
  357. WriteZeros(8); // CodeManagerTable
  358. WriteZeros(8); // VTableFixups NYI
  359. WriteZeros(16); // ExportAddressTableJumps, ManagedNativeHeader
  360. }
  361. private void WriteSDataSection()
  362. {
  363. long size = sdata.Size ();
  364. long start = BaseStream.Position;
  365. for (int i=0; i < data.Count; i++) {
  366. ((DataConstant)data[i]).Write(this);
  367. }
  368. while (BaseStream.Position < (start + size))
  369. Write ((byte) 0);
  370. }
  371. private void WriteRsrcSection()
  372. {
  373. }
  374. private void WriteRelocSection()
  375. {
  376. // Console.WriteLine("Writing reloc section at " + Seek(0,SeekOrigin.Current) + " = " + relocOffset);
  377. MemoryStream str = (MemoryStream)reloc.BaseStream;
  378. Write(str.ToArray());
  379. WriteZeros(NumToAlign((uint)str.Position,fileAlign));
  380. }
  381. internal void SetEntryPoint(uint entryPoint)
  382. {
  383. entryPointToken = entryPoint;
  384. }
  385. internal void AddInitData(DataConstant cVal)
  386. {
  387. if (sdata == null) {
  388. sdata = new Section(sdataName,0xC0000040); // IMAGE_SCN_CNT INITIALIZED_DATA, READ, WRITE
  389. data = new ArrayList();
  390. }
  391. data.Add(cVal);
  392. cVal.DataOffset = sdata.Tide();
  393. sdata.IncTide(cVal.GetSize());
  394. }
  395. internal void WriteZeros(uint numZeros)
  396. {
  397. for (int i=0; i < numZeros; i++) {
  398. Write((byte)0);
  399. }
  400. }
  401. internal void WritePEHeader()
  402. {
  403. Write((ushort)0x014C); // Machine - always 0x14C for Managed PE Files (allow others??)
  404. Write((ushort)numSections);
  405. Write(dateStamp);
  406. WriteZeros(8); // Pointer to Symbol Table and Number of Symbols (always zero for ECMA CLI files)
  407. Write((ushort)0x00E0); // Size of Optional Header
  408. Write(characteristics);
  409. // PE Optional Header
  410. Write((ushort)0x010B); // Magic
  411. Write((byte)0x6); // LMajor pure-IL = 6 C++ = 7
  412. Write((byte)0x0); // LMinor
  413. Write(text.Size());
  414. Write(initDataSize);
  415. Write(0); // Check other sections here!!
  416. Write(text.RVA() + entryPointOffset);
  417. Write(text.RVA());
  418. uint dataBase = 0;
  419. if (sdata != null) dataBase = sdata.RVA();
  420. else if (rsrc != null) dataBase = rsrc.RVA();
  421. else dataBase = relocRVA;
  422. Write(dataBase);
  423. Write(ImageBase);
  424. Write(SectionAlignment);
  425. Write(fileAlign);
  426. Write((ushort)0x04); // OS Major
  427. WriteZeros(6); // OS Minor, User Major, User Minor
  428. Write((ushort)0x04); // SubSys Major
  429. WriteZeros(6); // SybSys Minor, Reserved
  430. Write(imageSize);
  431. Write(headerSize);
  432. Write((int)0); // File Checksum
  433. Write((ushort)subSys);
  434. Write((short)0); // DLL Flags
  435. Write((uint)stackReserve); // Stack Reserve Size
  436. Write((uint)0x1000); // Stack Commit Size
  437. Write((uint)0x100000); // Heap Reserve Size
  438. Write((uint)0x1000); // Heap Commit Size
  439. Write(0); // Loader Flags
  440. Write(0x10); // Number of Data Directories
  441. WriteZeros(8); // Export Table
  442. Write(importTableOffset + text.RVA());
  443. Write(totalImportTableSize);
  444. WriteZeros(24); // Resource, Exception and Certificate Tables
  445. Write(relocRVA);
  446. Write(relocTide);
  447. WriteZeros(48); // Debug, Copyright, Global Ptr, TLS, Load Config and Bound Import Tables
  448. Write(text.RVA()); // IATRVA - IAT is at start of .text Section
  449. Write(IATSize);
  450. WriteZeros(8); // Delay Import Descriptor
  451. Write(text.RVA()+IATSize); // CLIHeader immediately follows IAT
  452. Write(CLIHeaderSize);
  453. WriteZeros(8); // Reserved
  454. }
  455. internal void WriteRelocSectionHeader()
  456. {
  457. Write(relocName.ToCharArray());
  458. Write(relocTide);
  459. Write(relocRVA);
  460. Write(relocSize);
  461. Write(relocOffset);
  462. WriteZeros(12);
  463. Write(relocFlags);
  464. }
  465. private void Align (MemoryStream str, int val)
  466. {
  467. if ((str.Position % val) != 0) {
  468. for (int i=val - (int)(str.Position % val); i > 0; i--) {
  469. str.WriteByte(0);
  470. }
  471. }
  472. }
  473. private uint Align(uint val, uint alignVal)
  474. {
  475. if ((val % alignVal) != 0) {
  476. val += alignVal - (val % alignVal);
  477. }
  478. return val;
  479. }
  480. private uint NumToAlign(uint val, uint alignVal)
  481. {
  482. if ((val % alignVal) == 0) return 0;
  483. return alignVal - (val % alignVal);
  484. }
  485. internal void StringsIndex(uint ix)
  486. {
  487. if (largeStrings) Write(ix);
  488. else Write((ushort)ix);
  489. }
  490. internal void GUIDIndex(uint ix)
  491. {
  492. if (largeGUID) Write(ix);
  493. else Write((ushort)ix);
  494. }
  495. internal void USIndex(uint ix)
  496. {
  497. if (largeUS) Write(ix);
  498. else Write((ushort)ix);
  499. }
  500. internal void BlobIndex(uint ix)
  501. {
  502. if (largeBlob) Write(ix);
  503. else Write((ushort)ix);
  504. }
  505. internal void WriteIndex(MDTable tabIx,uint ix)
  506. {
  507. if (metaData.LargeIx(tabIx)) Write(ix);
  508. else Write((ushort)ix);
  509. }
  510. internal void WriteCodedIndex(CIx code, MetaDataElement elem)
  511. {
  512. metaData.WriteCodedIndex(code,elem,this);
  513. }
  514. internal void WriteCodeRVA(uint offs)
  515. {
  516. Write(text.RVA() + offs);
  517. }
  518. internal void WriteDataRVA(uint offs)
  519. {
  520. Write(sdata.RVA() + offs);
  521. }
  522. internal void Write3Bytes(uint val)
  523. {
  524. byte b3 = (byte)((val & FileImage.iByteMask[2]) >> 16);
  525. byte b2 = (byte)((val & FileImage.iByteMask[1]) >> 8);;
  526. byte b1 = (byte)(val & FileImage.iByteMask[0]);
  527. Write(b1);
  528. Write(b2);
  529. Write(b3);
  530. }
  531. internal bool ReserveStrongNameSignatureSpace {
  532. get { return reserveStrongNameSignatureSpace; }
  533. set { reserveStrongNameSignatureSpace = value; }
  534. }
  535. }
  536. /**************************************************************************/
  537. /// <summary>
  538. /// Base class for the PEFile (starting point)
  539. /// </summary>
  540. public class PEFile {
  541. private static readonly string mscorlibName = "mscorlib";
  542. private Module thisMod;
  543. private ClassDef moduleClass;
  544. private ArrayList classRefList = new ArrayList();
  545. private ArrayList classDefList = new ArrayList();
  546. private ArrayList resources = new ArrayList ();
  547. private Assembly thisAssembly;
  548. private static bool isMSCorlib;
  549. private int corFlags = 1;
  550. FileImage fileImage;
  551. MetaData metaData;
  552. /// <summary>
  553. /// Create a new PEFile. Each PEFile is a module.
  554. /// </summary>
  555. /// <param name="name">module name, also used for the file name</param>
  556. /// <param name="isDLL">create a .dll or .exe file</param>
  557. /// <param name="hasAssembly">this file is an assembly and
  558. /// will contain the assembly manifest. The assembly name is the
  559. /// same as the module name</param>
  560. public PEFile(string name, bool isDLL, bool hasAssembly)
  561. : this (name, null, isDLL, hasAssembly, null, null)
  562. {
  563. // Console.WriteLine(Hex.Byte(0x12));
  564. // Console.WriteLine(Hex.Short(0x1234));
  565. // Console.WriteLine(Hex.Int(0x12345678));
  566. }
  567. /// <summary>
  568. /// Create a new PEFile. Each PEFile is a module.
  569. /// </summary>
  570. /// <param name="name">module name, also used for the file name</param>
  571. /// <param name="isDLL">create a .dll or .exe file</param>
  572. /// <param name="hasAssembly">this file is an assembly and
  573. /// will contain the assembly manifest. The assembly name is the
  574. /// same as the module name</param>
  575. /// <param name="outputDir">write the PEFile to this directory. If this
  576. /// string is null then the output will be to the current directory</param>
  577. public PEFile(string name, bool isDLL, bool hasAssembly, string outputDir)
  578. : this (name, null, isDLL, hasAssembly, outputDir, null)
  579. {
  580. // Console.WriteLine(Hex.Byte(0x12));
  581. // Console.WriteLine(Hex.Short(0x1234));
  582. // Console.WriteLine(Hex.Int(0x12345678));
  583. }
  584. /// <summary>
  585. /// Create a new PEFile
  586. /// </summary>
  587. /// <param name="name">module name</param>
  588. /// <param name="isDLL">create a .dll or .exe</param>
  589. /// <param name="hasAssembly">this PEfile is an assembly and
  590. /// will contain the assemly manifest. The assembly name is the
  591. /// same as the module name</param>
  592. /// <param name="outStream">write the PEFile to this stream instead
  593. /// of to a new file</param>
  594. public PEFile(string name, bool isDLL, bool hasAssembly, Stream outStream)
  595. : this (name, null, isDLL, hasAssembly, null, outStream)
  596. {
  597. }
  598. public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, Stream outStream)
  599. : this (name, module_name, isDLL, hasAssembly, null, outStream)
  600. {
  601. }
  602. public PEFile(string name, string module_name, bool isDLL, bool hasAssembly, string outputDir, Stream outStream)
  603. {
  604. SetName (name);
  605. string fname = module_name == null ? MakeFileName (outputDir, name, isDLL) : module_name;
  606. if (outStream == null)
  607. fileImage = new FileImage (isDLL, fname);
  608. else
  609. fileImage = new FileImage (isDLL, outStream);
  610. InitPEFile (name, fname, hasAssembly);
  611. }
  612. private void SetName (string name)
  613. {
  614. if (name == "mscorlib")
  615. isMSCorlib = true;
  616. }
  617. private void InitPEFile(string name, string fName, bool hasAssembly)
  618. {
  619. metaData = fileImage.GetMetaData();
  620. thisMod = new Module(fName,metaData);
  621. if (hasAssembly) {
  622. thisAssembly = new Assembly(name,metaData);
  623. metaData.AddToTable(MDTable.Assembly,thisAssembly);
  624. }
  625. moduleClass = AddClass(TypeAttr.Private,"","<Module>");
  626. moduleClass.SpecialNoSuper();
  627. metaData.AddToTable(MDTable.Module,thisMod);
  628. }
  629. internal static bool IsMSCorlib {
  630. get { return isMSCorlib; }
  631. }
  632. public ClassDef ModuleClass {
  633. get { return moduleClass; }
  634. }
  635. /// <summary>
  636. /// Set the subsystem (.subsystem) (Default is Windows Console mode)
  637. /// </summary>
  638. /// <param name="subS">subsystem value</param>
  639. public void SetSubSystem(SubSystem subS)
  640. {
  641. fileImage.subSys = subS;
  642. }
  643. /// <summary>
  644. /// Set the flags (.corflags)
  645. /// </summary>
  646. /// <param name="flags">the flags value</param>
  647. public void SetCorFlags(int flags)
  648. {
  649. corFlags = flags;
  650. }
  651. public void SetStackReserve (long stackReserve)
  652. {
  653. fileImage.stackReserve = stackReserve;
  654. }
  655. private string MakeFileName(string dirName, string name, bool isDLL)
  656. {
  657. string result = "";
  658. if ((dirName != null) && (dirName.CompareTo("") != 0)) {
  659. result = dirName;
  660. if (!dirName.EndsWith("\\")) result += "\\";
  661. }
  662. result += name;
  663. // if (isDLL) result += ".dll"; else result += ".exe";
  664. return result;
  665. }
  666. /// <summary>
  667. /// Add an external assembly to this PEFile (.assembly extern)
  668. /// </summary>
  669. /// <param name="assemName">the external assembly name</param>
  670. /// <returns>a descriptor for this external assembly</returns>
  671. public AssemblyRef AddExternAssembly(string assemName)
  672. {
  673. if (assemName.CompareTo(mscorlibName) == 0) return metaData.mscorlib;
  674. AssemblyRef anAssem = new AssemblyRef(metaData,assemName);
  675. metaData.AddToTable(MDTable.AssemblyRef,anAssem);
  676. // Console.WriteLine("Adding assembly " + assemName);
  677. return anAssem;
  678. }
  679. /// <summary>
  680. /// Add an external module to this PEFile (.module extern)
  681. /// </summary>
  682. /// <param name="name">the external module name</param>
  683. /// <returns>a descriptor for this external module</returns>
  684. public ModuleRef AddExternModule(string name)
  685. {
  686. ModuleRef modRef = new ModuleRef(metaData,name);
  687. metaData.AddToTable(MDTable.ModuleRef,modRef);
  688. return modRef;
  689. }
  690. /// <summary>
  691. /// Add a "global" method to this module
  692. /// </summary>
  693. /// <param name="name">method name</param>
  694. /// <param name="retType">return type</param>
  695. /// <param name="pars">method parameters</param>
  696. /// <returns>a descriptor for this new "global" method</returns>
  697. public MethodDef AddMethod(string name, Type retType, Param[] pars)
  698. {
  699. return moduleClass.AddMethod(name,retType,pars);
  700. }
  701. /// <summary>
  702. /// Add a "global" method to this module
  703. /// </summary>
  704. /// <param name="mAtts">method attributes</param>
  705. /// <param name="iAtts">method implementation attributes</param>
  706. /// <param name="name">method name</param>
  707. /// <param name="retType">return type</param>
  708. /// <param name="pars">method parameters</param>
  709. /// <returns>a descriptor for this new "global" method</returns>
  710. public MethodDef AddMethod(MethAttr mAtts, ImplAttr iAtts, string name, Type retType, Param[] pars)
  711. {
  712. return moduleClass.AddMethod(mAtts,iAtts,name,retType,pars);
  713. }
  714. public MethodRef AddMethodToTypeSpec (Type item, string name, Type retType, Type[] pars)
  715. {
  716. MethodRef meth = new MethodRef (item.GetTypeSpec (metaData), name, retType, pars, false, null);
  717. metaData.AddToTable (MDTable.MemberRef,meth);
  718. return meth;
  719. }
  720. public MethodRef AddVarArgMethodToTypeSpec (Type item, string name, Type retType,
  721. Type[] pars, Type[] optPars) {
  722. MethodRef meth = new MethodRef(item.GetTypeSpec (metaData), name,retType,pars,true,optPars);
  723. metaData.AddToTable(MDTable.MemberRef,meth);
  724. return meth;
  725. }
  726. public FieldRef AddFieldToTypeSpec (Type item, string name, Type fType)
  727. {
  728. FieldRef field = new FieldRef (item.GetTypeSpec (metaData), name,fType);
  729. metaData.AddToTable (MDTable.MemberRef,field);
  730. return field;
  731. }
  732. public void AddMethodSpec (Method m, GenericMethodSig g_sig)
  733. {
  734. MethodSpec ms = new MethodSpec (m, g_sig);
  735. metaData.AddToTable (MDTable.MethodSpec, ms);
  736. }
  737. /// <summary>
  738. /// Add a "global" field to this module
  739. /// </summary>
  740. /// <param name="name">field name</param>
  741. /// <param name="fType">field type</param>
  742. /// <returns>a descriptor for this new "global" field</returns>
  743. public FieldDef AddField(string name, Type fType)
  744. {
  745. return moduleClass.AddField(name,fType);
  746. }
  747. /// <summary>
  748. /// Add a "global" field to this module
  749. /// </summary>
  750. /// <param name="attrSet">attributes of this field</param>
  751. /// <param name="name">field name</param>
  752. /// <param name="fType">field type</param>
  753. /// <returns>a descriptor for this new "global" field</returns>
  754. public FieldDef AddField(FieldAttr attrSet, string name, Type fType)
  755. {
  756. return moduleClass.AddField(attrSet,name,fType);
  757. }
  758. /// <summary>
  759. /// Add a class to this module
  760. /// </summary>
  761. /// <param name="attrSet">attributes of this class</param>
  762. /// <param name="nsName">name space name</param>
  763. /// <param name="name">class name</param>
  764. /// <returns>a descriptor for this new class</returns>
  765. public ClassDef AddClass(TypeAttr attrSet, string nsName, string name)
  766. {
  767. return AddClass (attrSet, nsName, name, null);
  768. }
  769. /// <summary>
  770. /// Add a class which extends System.ValueType to this module
  771. /// </summary>
  772. /// <param name="attrSet">attributes of this class</param>
  773. /// <param name="nsName">name space name</param>
  774. /// <param name="name">class name</param>
  775. /// <returns>a descriptor for this new class</returns>
  776. public ClassDef AddValueClass(TypeAttr attrSet, string nsName, string name, ValueClass vClass)
  777. {
  778. ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
  779. if (!ClassDef.IsValueType (nsName, name) && !ClassDef.IsEnum (nsName, name)) {
  780. aClass.MakeValueClass(vClass);
  781. } else {
  782. if (ClassDef.IsEnum (nsName, name))
  783. aClass.SetSuper (metaData.mscorlib.ValueType ());
  784. else
  785. aClass.SetSuper (metaData.mscorlib.GetSpecialSystemClass (PrimitiveType.Object));
  786. metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
  787. }
  788. aClass.SetTypeIndex (PrimitiveType.ValueType.GetTypeIndex ());
  789. metaData.AddToTable(MDTable.TypeDef,aClass);
  790. return aClass;
  791. }
  792. /// <summary>
  793. /// Add a class to this module
  794. /// </summary>
  795. /// <param name="attrSet">attributes of this class</param>
  796. /// <param name="nsName">name space name</param>
  797. /// <param name="name">class name</param>
  798. /// <param name="superType">super type of this class (extends)</param>
  799. /// <returns>a descriptor for this new class</returns>
  800. public ClassDef AddClass(TypeAttr attrSet, string nsName, string name, Class superType)
  801. {
  802. ClassDef aClass = new ClassDef(attrSet,nsName,name,metaData);
  803. if (superType != null)
  804. aClass.SetSuper(superType);
  805. if (PEFile.IsMSCorlib)
  806. metaData.mscorlib.SetSpecialSystemClass (nsName, name, aClass);
  807. metaData.AddToTable(MDTable.TypeDef,aClass);
  808. return aClass;
  809. }
  810. public FileRef AddFile(string fName, byte[] hashBytes, bool hasMetaData, bool entryPoint)
  811. {
  812. FileRef file = new FileRef(fName,hashBytes,hasMetaData,entryPoint,metaData);
  813. metaData.AddToTable(MDTable.File,file);
  814. return file;
  815. }
  816. /// <summary>
  817. /// Add a manifest resource to this PEFile NOT YET IMPLEMENTED
  818. /// </summary>
  819. /// <param name="mr"></param>
  820. public void AddManifestResource(ManifestResource mr)
  821. {
  822. metaData.AddToTable(MDTable.ManifestResource,mr);
  823. resources.Add (mr);
  824. //mr.FixName(metaData);
  825. }
  826. public void AddCustomAttribute (Method meth, byte [] data, MetaDataElement element)
  827. {
  828. metaData.AddCustomAttribute (new CustomAttribute (element, meth, data));
  829. }
  830. public void AddDeclSecurity (SecurityAction sec_action, byte [] data, MetaDataElement element)
  831. {
  832. metaData.AddDeclSecurity (new DeclSecurity (element, (ushort) sec_action, data));
  833. }
  834. /// <summary>
  835. /// Add a managed resource from another assembly.
  836. /// </summary>
  837. /// <param name="resName">The name of the resource</param>
  838. /// <param name="assem">The assembly where the resource is</param>
  839. /// <param name="isPublic">Access for the resource</param>
  840. public void AddExternalManagedResource (string resName, AssemblyRef assem, uint flags)
  841. {
  842. resources.Add (new ManifestResource (resName, flags, assem));
  843. }
  844. /// <summary>
  845. /// Add a managed resource from another assembly.
  846. /// </summary>
  847. /// <param name="mr"></param>
  848. /// <param name="isPublic"></param>
  849. public void AddExternalManagedResource (ManifestResource mr)
  850. {
  851. resources.Add (new ManifestResource (mr));
  852. }
  853. /// <summary>
  854. /// Find a resource
  855. /// </summary>
  856. /// <param name="name">The name of the resource</param>
  857. /// <returns>The resource with the name "name" or null </returns>
  858. public ManifestResource GetResource (string name)
  859. {
  860. for (int i = 0; i < resources.Count; i ++) {
  861. if (((ManifestResource) resources [i]).Name == name)
  862. return (ManifestResource) resources [i];
  863. }
  864. return null;
  865. }
  866. public ManifestResource [] GetResources()
  867. {
  868. return (ManifestResource []) resources.ToArray (typeof (ManifestResource));
  869. }
  870. /// <summary>
  871. /// Write out the PEFile (the "bake" function)
  872. /// </summary>
  873. public void WritePEFile() { /* the "bake" function */
  874. fileImage.ReserveStrongNameSignatureSpace = thisAssembly.HasPublicKey;
  875. fileImage.MakeFile();
  876. }
  877. /// <summary>
  878. /// Get the descriptor of this module
  879. /// </summary>
  880. /// <returns>the descriptor for this module</returns>
  881. public Module GetThisModule()
  882. {
  883. return thisMod;
  884. }
  885. /// <summary>
  886. /// Get the descriptor for this assembly. The PEFile must have been
  887. /// created with hasAssembly = true
  888. /// </summary>
  889. /// <returns>the descriptor for this assembly</returns>
  890. public Assembly GetThisAssembly()
  891. {
  892. return thisAssembly;
  893. }
  894. }
  895. /**************************************************************************/
  896. /// <summary>
  897. /// Descriptor for a Section in a PEFile eg .text, .sdata
  898. /// </summary>
  899. internal class Section {
  900. private static readonly uint relocPageSize = 4096; // 4K pages for fixups
  901. char[] name;
  902. uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0;
  903. //uint relocOff = 0;
  904. uint flags = 0, padding = 0;
  905. uint[] relocs;
  906. internal Section(string sName, uint sFlags)
  907. {
  908. name = sName.ToCharArray();
  909. flags = sFlags;
  910. }
  911. internal uint Tide() { return tide; }
  912. internal void IncTide(uint incVal) { tide += incVal; }
  913. internal uint Padding() { return padding; }
  914. internal uint Size() { return size; }
  915. internal void SetSize(uint pad)
  916. {
  917. padding = pad;
  918. size = tide + padding;
  919. }
  920. internal uint RVA() { return rva; }
  921. internal void SetRVA(uint rva) { this.rva = rva; }
  922. internal uint Offset() { return offset; }
  923. internal void SetOffset(uint offs) { offset = offs; }
  924. internal void DoBlock(BinaryWriter reloc, uint page, int start, int end)
  925. {
  926. //Console.WriteLine("rva = " + rva + " page = " + page);
  927. reloc.Write(rva + page);
  928. reloc.Write((uint)(((end-start+1)*2) + 8));
  929. for (int j=start; j < end; j++) {
  930. //Console.WriteLine("reloc offset = " + relocs[j]);
  931. reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
  932. }
  933. reloc.Write((ushort)0);
  934. }
  935. internal void DoRelocs(BinaryWriter reloc)
  936. {
  937. if (relocTide > 0) {
  938. //relocOff = (uint)reloc.Seek(0,SeekOrigin.Current);
  939. uint block = (relocs[0]/relocPageSize + 1) * relocPageSize;
  940. int start = 0;
  941. for (int i=1; i < relocTide; i++) {
  942. if (relocs[i] >= block) {
  943. DoBlock(reloc,block-relocPageSize,start,i);
  944. start = i;
  945. block = (relocs[i]/relocPageSize + 1) * relocPageSize;
  946. }
  947. }
  948. DoBlock(reloc,block-relocPageSize,start,(int)relocTide);
  949. }
  950. }
  951. internal void AddReloc(uint offs)
  952. {
  953. int pos = 0;
  954. if (relocs == null) {
  955. relocs = new uint[5];
  956. } else {
  957. if (relocTide >= relocs.Length) {
  958. uint[] tmp = relocs;
  959. relocs = new uint[tmp.Length + 5];
  960. for (int i=0; i < relocTide; i++) {
  961. relocs[i] = tmp[i];
  962. }
  963. }
  964. while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
  965. for (int i=pos; i < relocTide; i++) {
  966. relocs[i+1] = relocs[i];
  967. }
  968. }
  969. relocs[pos] = offs;
  970. relocTide++;
  971. }
  972. internal void WriteHeader(BinaryWriter output, uint relocRVA)
  973. {
  974. output.Write(name);
  975. output.Write(tide);
  976. output.Write(rva);
  977. output.Write(size);
  978. output.Write(offset);
  979. output.Write(0);
  980. //output.Write(relocRVA + relocOff);
  981. output.Write(0);
  982. output.Write(0);
  983. //output.Write((ushort)relocTide);
  984. //output.Write((ushort)0);
  985. output.Write(flags);
  986. }
  987. }
  988. public class Hex {
  989. readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
  990. '8','9','A','B','C','D','E','F'};
  991. readonly static uint[] iByteMask = {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000};
  992. readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
  993. 0x0000000000FF0000, 0x00000000FF000000,
  994. 0x000000FF00000000, 0x0000FF0000000000,
  995. 0x00FF000000000000, 0xFF00000000000000 };
  996. readonly static uint nibble0Mask = 0x0000000F;
  997. readonly static uint nibble1Mask = 0x000000F0;
  998. public static String Byte(int b)
  999. {
  1000. char[] str = new char[2];
  1001. uint num = (uint)b;
  1002. uint b1 = num & nibble0Mask;
  1003. uint b2 = (num & nibble1Mask) >> 4;
  1004. str[0] = hexDigit[b2];
  1005. str[1] = hexDigit[b1];
  1006. return new String(str);
  1007. }
  1008. public static String Short(int b)
  1009. {
  1010. char[] str = new char[4];
  1011. uint num1 = (uint)b & iByteMask[0];
  1012. uint num2 = ((uint)b & iByteMask[1]) >> 8;
  1013. uint b1 = num1 & nibble0Mask;
  1014. uint b2 = (num1 & nibble1Mask) >> 4;
  1015. uint b3 = num2 & nibble0Mask;
  1016. uint b4 = (num2 & nibble1Mask) >> 4;
  1017. str[0] = hexDigit[b4];
  1018. str[1] = hexDigit[b3];
  1019. str[2] = hexDigit[b2];
  1020. str[3] = hexDigit[b1];
  1021. return new String(str);
  1022. }
  1023. public static String Int(int val)
  1024. {
  1025. char[] str = new char[8];
  1026. uint num = (uint)val;
  1027. int strIx = 7;
  1028. for (int i=0; i < iByteMask.Length; i++) {
  1029. uint b = num & iByteMask[i];
  1030. b >>= (i*8);
  1031. uint b1 = b & nibble0Mask;
  1032. uint b2 = (b & nibble1Mask) >> 4;
  1033. str[strIx--] = hexDigit[b1];
  1034. str[strIx--] = hexDigit[b2];
  1035. }
  1036. return new String(str);
  1037. }
  1038. public static String Int(uint num)
  1039. {
  1040. char[] str = new char[8];
  1041. int strIx = 7;
  1042. for (int i=0; i < iByteMask.Length; i++) {
  1043. uint b = num & iByteMask[i];
  1044. b >>= (i*8);
  1045. uint b1 = b & nibble0Mask;
  1046. uint b2 = (b & nibble1Mask) >> 4;
  1047. str[strIx--] = hexDigit[b1];
  1048. str[strIx--] = hexDigit[b2];
  1049. }
  1050. return new String(str);
  1051. }
  1052. public static String Long(long lnum)
  1053. {
  1054. ulong num = (ulong)lnum;
  1055. char[] str = new char[16];
  1056. int strIx = 15;
  1057. for (int i=0; i < lByteMask.Length; i++) {
  1058. ulong b = num & lByteMask[i];
  1059. b >>= (i*8);
  1060. ulong b1 = b & nibble0Mask;
  1061. ulong b2 = (b & nibble1Mask) >> 4;
  1062. str[strIx--] = hexDigit[b1];
  1063. str[strIx--] = hexDigit[b2];
  1064. }
  1065. return new String(str);
  1066. }
  1067. }
  1068. /// <summary>
  1069. /// Error for invalid PE file
  1070. /// </summary>
  1071. public class PEFileException : System.Exception {
  1072. public PEFileException(string msg) : base("Error in PE File: " + msg) { }
  1073. }
  1074. public class NotYetImplementedException : System.Exception {
  1075. public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
  1076. }
  1077. public class TypeSignatureException : System.Exception {
  1078. public TypeSignatureException(string msg) : base(msg) { }
  1079. }
  1080. }