Utils.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. namespace QUT.PERWAPI
  19. {
  20. /// <summary>
  21. /// Diagnostic
  22. /// </summary>
  23. public class Diag
  24. {
  25. /// <summary>
  26. /// Flag for diagnostic output.
  27. /// </summary>
  28. public static bool DiagOn = false;
  29. }
  30. public static class BlobUtil
  31. {
  32. public static byte[] CompressInt(int val)
  33. {
  34. // This code is based on a revised version of the
  35. // ECMA-335 spec which clarifies the encoding of
  36. // array lower bounds. (kjg 2008-Feb-22 )
  37. //
  38. uint uVal = ((uint)val) << 1;
  39. uint sign = (val < 0 ? (uint)1 : 0);
  40. if (-64 <= val && val <= 63)
  41. {
  42. uVal = uVal & 0x7f | sign;
  43. return new byte[] { (byte)uVal };
  44. }
  45. else if (-8192 <= val && val <= 8191)
  46. {
  47. uVal = uVal & 0x3fff | 0x8000 | sign;
  48. return new byte[] { (byte)(uVal >> 8), (byte)uVal };
  49. }
  50. else if (-268435456 <= val && val <= 268435455)
  51. {
  52. uVal = uVal & 0x1fffffff | 0xc0000000 | sign;
  53. return new byte[] {
  54. (byte)(uVal >> 24),
  55. (byte)(uVal >> 16),
  56. (byte)(uVal >> 8),
  57. (byte)uVal };
  58. }
  59. else
  60. throw new OverflowException("Value cannot be compressed");
  61. }
  62. public static byte[] CompressUInt(uint val)
  63. {
  64. if (val > 0x1fffffff)
  65. throw new OverflowException("Value cannot be compressed");
  66. return CompressNum(val);
  67. }
  68. private static byte[] CompressNum(uint num)
  69. {
  70. byte[] rslt = null;
  71. if (num <= 0x7f)
  72. {
  73. rslt = new byte[1];
  74. rslt[0] = (byte)num;
  75. }
  76. else if (num <= 0x3fff)
  77. {
  78. rslt = new byte[2];
  79. rslt[0] = (byte)((num >> 8) | 0x80);
  80. rslt[1] = (byte)(num & 0xff);
  81. }
  82. else
  83. {
  84. rslt = new byte[4];
  85. rslt[0] = (byte)((num >> 24) | 0xc0);
  86. rslt[1] = (byte)((num >> 16) & 0xff);
  87. rslt[2] = (byte)((num >> 8) & 0xff);
  88. rslt[3] = (byte)(num & 0xff);
  89. }
  90. return rslt;
  91. }
  92. }
  93. /// <summary>
  94. /// Facilities for outputting hexadecimal strings
  95. /// </summary>
  96. public class Hex
  97. {
  98. readonly static char[] hexDigit = {'0','1','2','3','4','5','6','7',
  99. '8','9','A','B','C','D','E','F'};
  100. readonly static uint[] iByteMask = { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 };
  101. readonly static ulong[] lByteMask = {0x00000000000000FF, 0x000000000000FF00,
  102. 0x0000000000FF0000, 0x00000000FF000000,
  103. 0x000000FF00000000, 0x0000FF0000000000,
  104. 0x00FF000000000000, 0xFF00000000000000 };
  105. readonly static uint nibble0Mask = 0x0000000F;
  106. readonly static uint nibble1Mask = 0x000000F0;
  107. /// <summary>
  108. /// Derives a hexadecimal string for a byte value
  109. /// </summary>
  110. /// <param name="b">the byte value</param>
  111. /// <returns>hex string for the byte value</returns>
  112. public static String Byte(int b)
  113. {
  114. char[] str = new char[2];
  115. uint num = (uint)b;
  116. uint b1 = num & nibble0Mask;
  117. uint b2 = (num & nibble1Mask) >> 4;
  118. str[0] = hexDigit[b2];
  119. str[1] = hexDigit[b1];
  120. return new String(str);
  121. }
  122. /// <summary>
  123. /// Derives a hexadecimal string for a short value
  124. /// </summary>
  125. /// <param name="b">the short value</param>
  126. /// <returns>hex string for the short value</returns>
  127. public static String Short(int b)
  128. {
  129. char[] str = new char[4];
  130. uint num1 = (uint)b & iByteMask[0];
  131. uint num2 = ((uint)b & iByteMask[1]) >> 8;
  132. uint b1 = num1 & nibble0Mask;
  133. uint b2 = (num1 & nibble1Mask) >> 4;
  134. uint b3 = num2 & nibble0Mask;
  135. uint b4 = (num2 & nibble1Mask) >> 4;
  136. str[0] = hexDigit[b4];
  137. str[1] = hexDigit[b3];
  138. str[2] = hexDigit[b2];
  139. str[3] = hexDigit[b1];
  140. return new String(str);
  141. }
  142. /// <summary>
  143. /// Derives a hexadecimal string for an int value
  144. /// </summary>
  145. /// <param name="val">the int value</param>
  146. /// <returns>hex string for the int value</returns>
  147. public static String Int(int val)
  148. {
  149. char[] str = new char[8];
  150. uint num = (uint)val;
  151. int strIx = 7;
  152. for (int i = 0; i < iByteMask.Length; i++)
  153. {
  154. uint b = num & iByteMask[i];
  155. b >>= (i * 8);
  156. uint b1 = b & nibble0Mask;
  157. uint b2 = (b & nibble1Mask) >> 4;
  158. str[strIx--] = hexDigit[b1];
  159. str[strIx--] = hexDigit[b2];
  160. }
  161. return new String(str);
  162. }
  163. /// <summary>
  164. /// Derives a hexadecimal string for an unsigned int value
  165. /// </summary>
  166. /// <param name="num">the unsigned int value</param>
  167. /// <returns>hex string for the unsigned int value</returns>
  168. public static String Int(uint num)
  169. {
  170. char[] str = new char[8];
  171. int strIx = 7;
  172. for (int i = 0; i < iByteMask.Length; i++)
  173. {
  174. uint b = num & iByteMask[i];
  175. b >>= (i * 8);
  176. uint b1 = b & nibble0Mask;
  177. uint b2 = (b & nibble1Mask) >> 4;
  178. str[strIx--] = hexDigit[b1];
  179. str[strIx--] = hexDigit[b2];
  180. }
  181. return new String(str);
  182. }
  183. /// <summary>
  184. /// Derives a hexadecimal string for a long value
  185. /// </summary>
  186. /// <param name="lnum">the long value</param>
  187. /// <returns>hex string for the long value</returns>
  188. public static String Long(long lnum)
  189. {
  190. ulong num = (ulong)lnum;
  191. return Long(num);
  192. }
  193. /// <summary>
  194. /// Derives a hexadecimal string for an unsigned long value
  195. /// </summary>
  196. /// <param name="num">the unsigned long value</param>
  197. /// <returns>hex string for the unsigned long value</returns>
  198. public static String Long(ulong num)
  199. {
  200. char[] str = new char[16];
  201. int strIx = 15;
  202. for (int i = 0; i < lByteMask.Length; i++)
  203. {
  204. ulong b = num & lByteMask[i];
  205. b >>= (i * 8);
  206. ulong b1 = b & nibble0Mask;
  207. ulong b2 = (b & nibble1Mask) >> 4;
  208. str[strIx--] = hexDigit[b1];
  209. str[strIx--] = hexDigit[b2];
  210. }
  211. return new String(str);
  212. }
  213. }
  214. /// <summary>
  215. /// Exception for features yet to be implemented
  216. /// </summary>
  217. public class NotYetImplementedException : System.Exception
  218. {
  219. /// <summary>
  220. /// constructor
  221. /// </summary>
  222. /// <param name="msg"></param>
  223. public NotYetImplementedException(string msg) : base(msg + " Not Yet Implemented") { }
  224. }
  225. /// <summary>
  226. /// Error in a type signature
  227. /// </summary>
  228. public class TypeSignatureException : System.Exception
  229. {
  230. /// <summary>
  231. /// constructor
  232. /// </summary>
  233. /// <param name="msg"></param>
  234. public TypeSignatureException(string msg) : base(msg) { }
  235. }
  236. /// <summary>
  237. /// Error with a CIL instruction
  238. /// </summary>
  239. public class InstructionException : System.Exception
  240. {
  241. IType iType;
  242. uint op;
  243. internal InstructionException(IType iType, uint op)
  244. {
  245. this.iType = iType;
  246. this.op = op;
  247. }
  248. internal string AddMethodName(string name)
  249. {
  250. string istr = " ";
  251. switch (iType)
  252. {
  253. case (IType.fieldOp): istr += (FieldOp)op; break;
  254. case (IType.methOp): istr += (MethodOp)op; break;
  255. case (IType.specialOp): istr += (SpecialOp)op; break;
  256. case (IType.typeOp): istr += (TypeOp)op; break;
  257. default: break;
  258. }
  259. return "NullPointer in instruction" + istr + " for method " + name;
  260. }
  261. }
  262. /// <summary>
  263. /// Error with descriptor types
  264. /// </summary>
  265. public class DescriptorException : System.Exception
  266. {
  267. /// <summary>
  268. /// exception
  269. /// </summary>
  270. /// <param name="msg"></param>
  271. public DescriptorException(string msg)
  272. :
  273. base("Descriptor for " + msg + " already exists") { }
  274. /// <summary>
  275. /// exception
  276. /// </summary>
  277. public DescriptorException()
  278. :
  279. base("Descriptor is a Def when a Ref is required") { }
  280. }
  281. /// <summary>
  282. /// Error for invalid PE file
  283. /// </summary>
  284. public class PEFileException : System.Exception
  285. {
  286. /// <summary>
  287. /// PEFile exception constructor
  288. /// </summary>
  289. /// <param name="msg"></param>
  290. public PEFileException(string msg) : base("Error in PE File: " + msg) { }
  291. }
  292. /// <summary>
  293. /// When the maximum stack depth could not be found dynamically.
  294. /// </summary>
  295. public class CouldNotFindMaxStackDepth : System.Exception
  296. {
  297. /// <summary>
  298. /// Constructor
  299. /// </summary>
  300. public CouldNotFindMaxStackDepth() : base("Not able to find the maximum stack depth.") { }
  301. }
  302. /// <summary>
  303. /// When the stack depth is not valid for the current position.
  304. /// </summary>
  305. public class InvalidStackDepth : System.Exception
  306. {
  307. /// <summary>
  308. /// Constructor
  309. /// </summary>
  310. public InvalidStackDepth(string msg) : base("Invalid stack depth reached: " + msg) { }
  311. }
  312. }