CodeBlocks.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  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.Collections;
  19. using System.Text;
  20. namespace QUT.PERWAPI
  21. {
  22. /**************************************************************************/
  23. public abstract class CodeBlock
  24. {
  25. private static readonly int maxCodeSize = 255;
  26. protected CILLabel start, end;
  27. protected bool small = true;
  28. /*-------------------- Constructors ---------------------------------*/
  29. public CodeBlock(CILLabel start, CILLabel end)
  30. {
  31. this.start = start;
  32. this.end = end;
  33. }
  34. /// <summary>
  35. /// The label that marks the start of this code block
  36. /// </summary>
  37. public CILLabel Start { get { return start; } }
  38. /// <summary>
  39. /// The label that marks the end of this code block
  40. /// </summary>
  41. public CILLabel End { get { return end; } }
  42. internal virtual bool isFat()
  43. {
  44. // Console.WriteLine("block start = " + start.GetLabelOffset() +
  45. // " block end = " + end.GetLabelOffset());
  46. return (end.GetLabelOffset() - start.GetLabelOffset()) > maxCodeSize;
  47. }
  48. internal virtual void Write(PEWriter output, bool fatFormat)
  49. {
  50. if (fatFormat) output.Write(start.GetLabelOffset());
  51. else output.Write((short)start.GetLabelOffset());
  52. uint len = end.GetLabelOffset() - start.GetLabelOffset();
  53. if (Diag.DiagOn) Console.WriteLine("block start = " + start.GetLabelOffset() + " len = " + len);
  54. if (fatFormat) output.Write(len);
  55. else output.Write((byte)len);
  56. }
  57. }
  58. /**************************************************************************/
  59. /// <summary>
  60. /// The descriptor for a guarded block (.try)
  61. /// </summary>
  62. public class TryBlock : CodeBlock
  63. {
  64. protected bool fatFormat = false;
  65. protected ushort flags = 0;
  66. ArrayList handlers = new ArrayList();
  67. /*-------------------- Constructors ---------------------------------*/
  68. /// <summary>
  69. /// Create a new try block
  70. /// </summary>
  71. /// <param name="start">start label for the try block</param>
  72. /// <param name="end">end label for the try block</param>
  73. public TryBlock(CILLabel start, CILLabel end) : base(start, end) { }
  74. /// <summary>
  75. /// Add a handler to this try block
  76. /// </summary>
  77. /// <param name="handler">a handler to be added to the try block</param>
  78. public void AddHandler(HandlerBlock handler)
  79. {
  80. //flags = handler.GetFlag();
  81. handlers.Add(handler);
  82. }
  83. /// <summary>
  84. /// Get an array containing all the handlers.
  85. /// </summary>
  86. /// <returns>The list of handlers.</returns>
  87. public HandlerBlock[] GetHandlers()
  88. {
  89. return (HandlerBlock[])handlers.ToArray(typeof(HandlerBlock));
  90. }
  91. internal void SetSize()
  92. {
  93. fatFormat = base.isFat();
  94. if (fatFormat) return;
  95. for (int i = 0; i < handlers.Count; i++)
  96. {
  97. HandlerBlock handler = (HandlerBlock)handlers[i];
  98. if (handler.isFat())
  99. {
  100. fatFormat = true;
  101. return;
  102. }
  103. }
  104. }
  105. internal int NumHandlers()
  106. {
  107. return handlers.Count;
  108. }
  109. internal override bool isFat()
  110. {
  111. return fatFormat;
  112. }
  113. internal void BuildTables(MetaDataOut md)
  114. {
  115. for (int i = 0; i < handlers.Count; i++)
  116. {
  117. ((HandlerBlock)handlers[i]).BuildTables(md);
  118. }
  119. }
  120. internal void BuildCILInfo(CILWriter output)
  121. {
  122. for (int i = 0; i < handlers.Count; i++)
  123. {
  124. ((HandlerBlock)handlers[i]).BuildCILInfo(output);
  125. }
  126. }
  127. internal override void Write(PEWriter output, bool fatFormat)
  128. {
  129. if (Diag.DiagOn) Console.WriteLine("writing exception details");
  130. for (int i = 0; i < handlers.Count; i++)
  131. {
  132. if (Diag.DiagOn) Console.WriteLine("Except block " + i);
  133. HandlerBlock handler = (HandlerBlock)handlers[i];
  134. flags = handler.GetFlag();
  135. if (Diag.DiagOn) Console.WriteLine("flags = " + flags);
  136. if (fatFormat) output.Write((uint)flags);
  137. else output.Write(flags);
  138. base.Write(output, fatFormat);
  139. handler.Write(output, fatFormat);
  140. }
  141. }
  142. }
  143. /**************************************************************************/
  144. public abstract class HandlerBlock : CodeBlock
  145. {
  146. protected static readonly ushort ExceptionFlag = 0;
  147. protected static readonly ushort FilterFlag = 0x01;
  148. protected static readonly ushort FinallyFlag = 0x02;
  149. protected static readonly ushort FaultFlag = 0x04;
  150. /*-------------------- Constructors ---------------------------------*/
  151. public HandlerBlock(CILLabel start, CILLabel end) : base(start, end) { }
  152. internal virtual ushort GetFlag()
  153. {
  154. if (Diag.DiagOn) Console.WriteLine("Catch Block");
  155. return ExceptionFlag;
  156. }
  157. internal virtual void BuildTables(MetaDataOut md) { }
  158. internal virtual void BuildCILInfo(CILWriter output) { }
  159. internal override void Write(PEWriter output, bool fatFormat)
  160. {
  161. base.Write(output, fatFormat);
  162. }
  163. }
  164. /**************************************************************************/
  165. /// <summary>
  166. /// The descriptor for a catch clause (.catch)
  167. /// </summary>
  168. public class Catch : HandlerBlock
  169. {
  170. Class exceptType;
  171. /*-------------------- Constructors ---------------------------------*/
  172. /// <summary>
  173. /// Create a new catch clause
  174. /// </summary>
  175. /// <param name="except">the exception to be caught</param>
  176. /// <param name="handlerStart">start of the handler code</param>
  177. /// <param name="handlerEnd">end of the handler code</param>
  178. public Catch(Class except, CILLabel handlerStart, CILLabel handlerEnd)
  179. : base(handlerStart, handlerEnd)
  180. {
  181. exceptType = except;
  182. }
  183. internal override void BuildTables(MetaDataOut md)
  184. {
  185. if (!(exceptType is ClassDef)) exceptType.BuildMDTables(md);
  186. }
  187. internal override void BuildCILInfo(CILWriter output)
  188. {
  189. if (!(exceptType is ClassDef)) exceptType.BuildCILInfo(output);
  190. }
  191. internal override void Write(PEWriter output, bool fatFormat)
  192. {
  193. base.Write(output, fatFormat);
  194. output.Write(exceptType.Token());
  195. }
  196. }
  197. /**************************************************************************/
  198. /// <summary>
  199. /// The descriptor for a filter clause (.filter)
  200. /// </summary>
  201. public class Filter : HandlerBlock
  202. {
  203. CILLabel filterLabel;
  204. /*-------------------- Constructors ---------------------------------*/
  205. /// <summary>
  206. /// Create a new filter clause
  207. /// </summary>
  208. /// <param name="filterLabel">the label where the filter code starts</param>
  209. /// <param name="handlerStart">the start of the handler code</param>
  210. /// <param name="handlerEnd">the end of the handler code</param>
  211. public Filter(CILLabel filterLabel, CILLabel handlerStart,
  212. CILLabel handlerEnd)
  213. : base(handlerStart, handlerEnd)
  214. {
  215. this.filterLabel = filterLabel;
  216. }
  217. internal override ushort GetFlag()
  218. {
  219. if (Diag.DiagOn) Console.WriteLine("Filter Block");
  220. return FilterFlag;
  221. }
  222. internal override void Write(PEWriter output, bool fatFormat)
  223. {
  224. base.Write(output, fatFormat);
  225. output.Write(filterLabel.GetLabelOffset());
  226. }
  227. }
  228. /**************************************************************************/
  229. /// <summary>
  230. /// Descriptor for a finally block (.finally)
  231. /// </summary>
  232. public class Finally : HandlerBlock
  233. {
  234. /*-------------------- Constructors ---------------------------------*/
  235. /// <summary>
  236. /// Create a new finally clause
  237. /// </summary>
  238. /// <param name="finallyStart">start of finally code</param>
  239. /// <param name="finallyEnd">end of finally code</param>
  240. public Finally(CILLabel finallyStart, CILLabel finallyEnd)
  241. : base(finallyStart, finallyEnd) { }
  242. internal override ushort GetFlag()
  243. {
  244. if (Diag.DiagOn) Console.WriteLine("Finally Block");
  245. return FinallyFlag;
  246. }
  247. internal override void Write(PEWriter output, bool fatFormat)
  248. {
  249. base.Write(output, fatFormat);
  250. output.Write((int)0);
  251. }
  252. }
  253. /**************************************************************************/
  254. /// <summary>
  255. /// Descriptor for a fault block (.fault)
  256. /// </summary>
  257. public class Fault : HandlerBlock
  258. {
  259. /*-------------------- Constructors ---------------------------------*/
  260. /// <summary>
  261. /// Create a new fault clause
  262. /// </summary>
  263. /// <param name="faultStart">start of the fault code</param>
  264. /// <param name="faultEnd">end of the fault code</param>
  265. public Fault(CILLabel faultStart, CILLabel faultEnd)
  266. : base(faultStart, faultEnd) { }
  267. internal override ushort GetFlag()
  268. {
  269. if (Diag.DiagOn) Console.WriteLine("Fault Block");
  270. return FaultFlag;
  271. }
  272. internal override void Write(PEWriter output, bool fatFormat)
  273. {
  274. base.Write(output, fatFormat);
  275. output.Write((int)0);
  276. }
  277. }
  278. }