Constants.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  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. namespace QUT.PERWAPI
  20. {
  21. /**************************************************************************/
  22. // Classes used to describe constant values
  23. /**************************************************************************/
  24. /// <summary>
  25. /// Descriptor for a constant value, to be written in the blob heap
  26. /// </summary>
  27. public abstract class Constant
  28. {
  29. protected uint size = 0;
  30. internal ElementType type;
  31. protected uint blobIndex;
  32. internal MetaDataOut addedToBlobHeap;
  33. /*-------------------- Constructors ---------------------------------*/
  34. internal Constant() { }
  35. internal virtual uint GetBlobIndex(MetaDataOut md) { return 0; }
  36. internal uint GetSize() { return size; }
  37. internal byte GetTypeIndex() { return (byte)type; }
  38. internal virtual void Write(BinaryWriter bw) { }
  39. internal virtual void Write(CILWriter output)
  40. {
  41. throw new NotYetImplementedException("Constant values for CIL");
  42. }
  43. }
  44. /**************************************************************************/
  45. public abstract class BlobConstant : Constant { }
  46. /**************************************************************************/
  47. /// <summary>
  48. /// Boolean constant
  49. /// </summary>
  50. public class BoolConst : BlobConstant
  51. {
  52. bool val;
  53. /*-------------------- Constructors ---------------------------------*/
  54. /// <summary>
  55. /// Create a new boolean constant with the value "val"
  56. /// </summary>
  57. /// <param name="val">value of this boolean constant</param>
  58. public BoolConst(bool val)
  59. {
  60. this.val = val;
  61. size = 1;
  62. type = ElementType.Boolean;
  63. }
  64. public bool GetBool()
  65. {
  66. return val;
  67. }
  68. internal sealed override uint GetBlobIndex(MetaDataOut md)
  69. {
  70. if (addedToBlobHeap != md)
  71. {
  72. if (val) blobIndex = md.AddToBlobHeap(1, 1);
  73. else blobIndex = md.AddToBlobHeap(0, 1);
  74. addedToBlobHeap = md;
  75. }
  76. return blobIndex;
  77. }
  78. internal sealed override void Write(BinaryWriter bw)
  79. {
  80. if (val) bw.Write((sbyte)1);
  81. else bw.Write((sbyte)0);
  82. }
  83. }
  84. /**************************************************************************/
  85. public class CharConst : BlobConstant
  86. {
  87. char val;
  88. /*-------------------- Constructors ---------------------------------*/
  89. public CharConst(char val)
  90. {
  91. this.val = val;
  92. size = 2;
  93. type = ElementType.Char;
  94. }
  95. internal CharConst(PEReader buff)
  96. {
  97. val = buff.ReadChar();
  98. size = 2;
  99. type = ElementType.Char;
  100. }
  101. public char GetChar()
  102. { // KJG addition 2005-Mar-01
  103. return val;
  104. }
  105. internal sealed override uint GetBlobIndex(MetaDataOut md)
  106. {
  107. if (addedToBlobHeap != md)
  108. {
  109. blobIndex = md.AddToBlobHeap(val);
  110. addedToBlobHeap = md;
  111. }
  112. return blobIndex;
  113. }
  114. internal sealed override void Write(BinaryWriter bw)
  115. {
  116. bw.Write(val);
  117. }
  118. }
  119. /**************************************************************************/
  120. public class NullRefConst : BlobConstant
  121. {
  122. /*-------------------- Constructors ---------------------------------*/
  123. public NullRefConst()
  124. {
  125. size = 4;
  126. type = ElementType.Class;
  127. }
  128. internal NullRefConst(PEReader buff)
  129. {
  130. uint junk = buff.ReadUInt32();
  131. size = 4;
  132. type = ElementType.Class;
  133. }
  134. internal sealed override uint GetBlobIndex(MetaDataOut md)
  135. {
  136. if (addedToBlobHeap != md)
  137. {
  138. blobIndex = md.AddToBlobHeap(0, 4);
  139. addedToBlobHeap = md;
  140. }
  141. return blobIndex;
  142. }
  143. internal sealed override void Write(BinaryWriter bw)
  144. {
  145. bw.Write((int)0);
  146. }
  147. }
  148. /**************************************************************************/
  149. /// <summary>
  150. /// Constant array
  151. /// </summary>
  152. public class ArrayConst : BlobConstant
  153. {
  154. Constant[] elements;
  155. /*-------------------- Constructors ---------------------------------*/
  156. public ArrayConst(Constant[] elems)
  157. {
  158. type = ElementType.SZArray;
  159. size = 5; // one byte for SZARRAY, 4 bytes for length
  160. elements = elems;
  161. for (int i = 0; i < elements.Length; i++)
  162. {
  163. size += elements[i].GetSize();
  164. }
  165. }
  166. public Constant[] GetArray()
  167. {
  168. return elements;
  169. }
  170. internal sealed override uint GetBlobIndex(MetaDataOut md)
  171. {
  172. if (addedToBlobHeap != md)
  173. {
  174. MemoryStream str = new MemoryStream();
  175. BinaryWriter bw = new BinaryWriter(str);
  176. Write(bw);
  177. blobIndex = md.AddToBlobHeap(str.ToArray());
  178. addedToBlobHeap = md;
  179. }
  180. return blobIndex;
  181. }
  182. internal sealed override void Write(BinaryWriter bw)
  183. {
  184. bw.Write((byte)type);
  185. bw.Write(elements.Length);
  186. for (int i = 0; i < elements.Length; i++)
  187. {
  188. elements[i].Write(bw);
  189. }
  190. }
  191. }
  192. /**************************************************************************/
  193. public class ClassTypeConst : BlobConstant
  194. {
  195. string name;
  196. Class desc;
  197. /*-------------------- Constructors ---------------------------------*/
  198. public ClassTypeConst(string className)
  199. {
  200. name = className;
  201. type = ElementType.ClassType;
  202. }
  203. public ClassTypeConst(Class classDesc)
  204. {
  205. desc = classDesc;
  206. type = ElementType.ClassType;
  207. }
  208. public Class GetClass()
  209. {
  210. return desc;
  211. }
  212. public String GetClassName()
  213. {
  214. if (name == null) name = desc.TypeName();
  215. // CHECK - ClassName or TypeName
  216. // if (name == null) return desc.ClassName();
  217. return name;
  218. }
  219. internal override void Write(BinaryWriter bw)
  220. {
  221. if (name == null) name = desc.TypeName();
  222. // CHECK - ClassName or TypeName
  223. // if (name == null) name = desc.ClassName();
  224. bw.Write(name);
  225. }
  226. }
  227. /**************************************************************************/
  228. public class BoxedSimpleConst : BlobConstant
  229. {
  230. SimpleConstant sConst;
  231. /*-------------------- Constructors ---------------------------------*/
  232. public BoxedSimpleConst(SimpleConstant con)
  233. {
  234. sConst = con;
  235. type = (ElementType)sConst.GetTypeIndex();
  236. }
  237. public SimpleConstant GetConst()
  238. {
  239. return sConst;
  240. }
  241. internal override void Write(BinaryWriter bw)
  242. {
  243. bw.Write((byte)type);
  244. sConst.Write(bw);
  245. }
  246. }
  247. /**************************************************************************/
  248. /// <summary>
  249. /// Descriptor for a constant value
  250. /// </summary>
  251. public abstract class DataConstant : Constant
  252. {
  253. private uint dataOffset = 0;
  254. /*-------------------- Constructors ---------------------------------*/
  255. internal DataConstant() { }
  256. public uint DataOffset
  257. {
  258. get { return dataOffset; }
  259. set { dataOffset = value; }
  260. }
  261. }
  262. /**************************************************************************/
  263. /// <summary>
  264. /// Constant for a memory address
  265. /// </summary>
  266. public class AddressConstant : DataConstant
  267. {
  268. DataConstant data;
  269. /*-------------------- Constructors ---------------------------------*/
  270. public AddressConstant(DataConstant dConst)
  271. {
  272. data = dConst;
  273. size = 4;
  274. type = ElementType.TypedByRef;
  275. }
  276. internal AddressConstant(PEReader buff)
  277. {
  278. }
  279. public DataConstant GetConst()
  280. {
  281. return data;
  282. }
  283. internal sealed override void Write(BinaryWriter bw)
  284. {
  285. ((PEWriter)bw).WriteDataRVA(data.DataOffset);
  286. }
  287. }
  288. /**************************************************************************/
  289. public class ByteArrConst : DataConstant
  290. {
  291. byte[] val;
  292. /*-------------------- Constructors ---------------------------------*/
  293. public ByteArrConst(byte[] val)
  294. {
  295. this.val = val;
  296. size = (uint)val.Length;
  297. }
  298. public byte[] GetArray()
  299. {
  300. return val;
  301. }
  302. internal sealed override uint GetBlobIndex(MetaDataOut md)
  303. {
  304. if (addedToBlobHeap != md)
  305. {
  306. blobIndex = md.AddToBlobHeap(val);
  307. addedToBlobHeap = md;
  308. }
  309. return blobIndex;
  310. }
  311. internal sealed override void Write(BinaryWriter bw)
  312. {
  313. bw.Write(val);
  314. }
  315. }
  316. /**************************************************************************/
  317. public class RepeatedConstant : DataConstant
  318. {
  319. DataConstant data;
  320. uint repCount;
  321. /*-------------------- Constructors ---------------------------------*/
  322. public RepeatedConstant(DataConstant dConst, int repeatCount)
  323. {
  324. data = dConst;
  325. repCount = (uint)repeatCount;
  326. type = ElementType.SZArray;
  327. size = data.GetSize() * repCount;
  328. }
  329. public DataConstant GetConst()
  330. {
  331. return data;
  332. }
  333. public uint GetCount()
  334. {
  335. return repCount;
  336. }
  337. internal sealed override void Write(BinaryWriter bw)
  338. {
  339. for (int i = 0; i < repCount; i++)
  340. {
  341. data.Write(bw);
  342. }
  343. }
  344. }
  345. /**************************************************************************/
  346. public class StringConst : DataConstant
  347. {
  348. string val;
  349. byte[] strBytes;
  350. /*-------------------- Constructors ---------------------------------*/
  351. public StringConst(string val)
  352. {
  353. this.val = val;
  354. size = (uint)val.Length; // need to add null ??
  355. type = ElementType.String;
  356. }
  357. internal StringConst(byte[] sBytes)
  358. {
  359. strBytes = sBytes;
  360. size = (uint)strBytes.Length;
  361. type = ElementType.String;
  362. }
  363. public string GetString()
  364. {
  365. return val;
  366. }
  367. public byte[] GetStringBytes()
  368. {
  369. return strBytes;
  370. }
  371. internal sealed override uint GetBlobIndex(MetaDataOut md)
  372. {
  373. if (addedToBlobHeap != md)
  374. {
  375. if (val == null)
  376. blobIndex = md.AddToBlobHeap(strBytes);
  377. else
  378. blobIndex = md.AddToBlobHeap(val);
  379. addedToBlobHeap = md;
  380. }
  381. return blobIndex;
  382. }
  383. internal sealed override void Write(BinaryWriter bw)
  384. {
  385. if ((val == null) && (strBytes != null))
  386. {
  387. bw.Write(strBytes);
  388. }
  389. else
  390. bw.Write(val);
  391. }
  392. }
  393. /**************************************************************************/
  394. public abstract class SimpleConstant : DataConstant { }
  395. /**************************************************************************/
  396. public class IntConst : SimpleConstant
  397. {
  398. long val;
  399. /*-------------------- Constructors ---------------------------------*/
  400. public IntConst(sbyte val)
  401. {
  402. this.val = val;
  403. size = 1; //8;
  404. type = ElementType.I8;
  405. }
  406. public IntConst(short val)
  407. {
  408. this.val = val;
  409. size = 2; //16;
  410. type = ElementType.I2;
  411. }
  412. public IntConst(int val)
  413. {
  414. this.val = val;
  415. size = 4; //32;
  416. type = ElementType.I4;
  417. }
  418. public IntConst(long val)
  419. {
  420. this.val = val;
  421. size = 8; //64;
  422. type = ElementType.I8;
  423. }
  424. internal IntConst(PEReader buff, int numBytes)
  425. {
  426. switch (numBytes)
  427. {
  428. case (1): val = buff.ReadSByte();
  429. type = ElementType.I8;
  430. break;
  431. case (2): val = buff.ReadInt16();
  432. type = ElementType.I2;
  433. break;
  434. case (4): val = buff.ReadInt32();
  435. type = ElementType.I4;
  436. break;
  437. case (8): val = buff.ReadInt64();
  438. type = ElementType.I8;
  439. break;
  440. default: val = 0;
  441. break;
  442. }
  443. size = (uint)numBytes; // * 4;
  444. }
  445. public int GetIntSize()
  446. {
  447. return (int)size;
  448. }
  449. public ElementType GetIntType()
  450. {
  451. return type;
  452. }
  453. public int GetInt()
  454. {
  455. if (size < 8)
  456. return (int)val;
  457. else
  458. throw new Exception("Constant is long");
  459. }
  460. public long GetLong()
  461. {
  462. return val;
  463. }
  464. internal sealed override uint GetBlobIndex(MetaDataOut md)
  465. {
  466. if (addedToBlobHeap != md)
  467. {
  468. blobIndex = md.AddToBlobHeap(val, size);
  469. //switch (size) {
  470. // case (1) : md.AddToBlobHeap((sbyte)val); break;
  471. // case (2) : md.AddToBlobHeap((short)val); break;
  472. // case (4) : md.AddToBlobHeap((int)val); break;
  473. // default : md.AddToBlobHeap(val); break;
  474. //}
  475. addedToBlobHeap = md;
  476. }
  477. return blobIndex;
  478. }
  479. internal sealed override void Write(BinaryWriter bw)
  480. {
  481. switch (size)
  482. {
  483. case (1): bw.Write((sbyte)val); break;
  484. case (2): bw.Write((short)val); break;
  485. case (4): bw.Write((int)val); break;
  486. default: bw.Write(val); break;
  487. }
  488. }
  489. }
  490. /**************************************************************************/
  491. public class UIntConst : SimpleConstant
  492. {
  493. ulong val;
  494. /*-------------------- Constructors ---------------------------------*/
  495. public UIntConst(byte val)
  496. {
  497. this.val = val;
  498. size = 1;
  499. type = ElementType.U8;
  500. }
  501. public UIntConst(ushort val)
  502. {
  503. this.val = val;
  504. size = 2;
  505. type = ElementType.U2;
  506. }
  507. public UIntConst(uint val)
  508. {
  509. this.val = val;
  510. size = 4;
  511. type = ElementType.U4;
  512. }
  513. public UIntConst(ulong val)
  514. {
  515. this.val = val;
  516. size = 8;
  517. type = ElementType.U8;
  518. }
  519. public int GetIntSize()
  520. {
  521. return (int)size;
  522. }
  523. public ElementType GetUIntType()
  524. {
  525. return type;
  526. }
  527. public uint GetUInt()
  528. {
  529. return (uint)val;
  530. }
  531. public ulong GetULong()
  532. {
  533. return val;
  534. }
  535. public long GetLong()
  536. { // KJG addition
  537. if (val <= (ulong)(System.Int64.MaxValue))
  538. return (long)val;
  539. else
  540. throw new Exception("UInt Constant too large");
  541. }
  542. public long GetULongAsLong()
  543. { // KJG addition
  544. return (long)val;
  545. }
  546. internal sealed override uint GetBlobIndex(MetaDataOut md)
  547. {
  548. if (addedToBlobHeap != md)
  549. {
  550. blobIndex = md.AddToBlobHeap(val, size);
  551. //switch (size) {
  552. // case (1) : blobIndex = md.AddToBlobHeap((byte)val); break;
  553. // case (2) : blobIndex = md.AddToBlobHeap((ushort)val); break;
  554. // case (4) : blobIndex = md.AddToBlobHeap((uint)val); break;
  555. // default : blobIndex = md.AddToBlobHeap(val); break;
  556. //}
  557. addedToBlobHeap = md;
  558. }
  559. return blobIndex;
  560. }
  561. internal sealed override void Write(BinaryWriter bw)
  562. {
  563. switch (size)
  564. {
  565. case (1): bw.Write((byte)val); break;
  566. case (2): bw.Write((ushort)val); break;
  567. case (4): bw.Write((uint)val); break;
  568. default: bw.Write(val); break;
  569. }
  570. }
  571. }
  572. /**************************************************************************/
  573. public class FloatConst : SimpleConstant
  574. {
  575. float val;
  576. /*-------------------- Constructors ---------------------------------*/
  577. public FloatConst(float val)
  578. {
  579. this.val = val;
  580. size = 4;
  581. type = ElementType.R4;
  582. }
  583. internal FloatConst(PEReader buff)
  584. {
  585. val = buff.ReadSingle();
  586. size = 4;
  587. type = ElementType.R4;
  588. }
  589. public float GetFloat()
  590. {
  591. return val;
  592. }
  593. public double GetDouble()
  594. { // KJG addition 2005-Mar-01
  595. return (double)val;
  596. }
  597. internal sealed override uint GetBlobIndex(MetaDataOut md)
  598. {
  599. if (addedToBlobHeap != md)
  600. {
  601. blobIndex = md.AddToBlobHeap(val);
  602. addedToBlobHeap = md;
  603. }
  604. return blobIndex;
  605. }
  606. internal sealed override void Write(BinaryWriter bw)
  607. {
  608. bw.Write(val);
  609. }
  610. }
  611. /**************************************************************************/
  612. public class DoubleConst : SimpleConstant
  613. {
  614. double val;
  615. /*-------------------- Constructors ---------------------------------*/
  616. public DoubleConst(double val)
  617. {
  618. this.val = val;
  619. size = 8;
  620. type = ElementType.R8;
  621. }
  622. internal DoubleConst(PEReader buff)
  623. {
  624. val = buff.ReadDouble();
  625. size = 8;
  626. type = ElementType.R8;
  627. }
  628. public double GetDouble()
  629. { // KJG addition 2005-Mar-01
  630. return val;
  631. }
  632. internal sealed override uint GetBlobIndex(MetaDataOut md)
  633. {
  634. if (addedToBlobHeap != md)
  635. {
  636. blobIndex = md.AddToBlobHeap(val);
  637. addedToBlobHeap = md;
  638. }
  639. return blobIndex;
  640. }
  641. internal sealed override void Write(BinaryWriter bw)
  642. {
  643. bw.Write(val);
  644. }
  645. }
  646. }