SectionClass.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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. // PE File Section Descriptor
  24. /**************************************************************************/
  25. /// <summary>
  26. /// Descriptor for a Section in a PEFile eg .text, .sdata
  27. /// </summary>
  28. internal class Section
  29. {
  30. internal static readonly uint relocPageSize = 4096; // 4K pages for fixups
  31. char[] name;
  32. string nameString;
  33. uint offset = 0, tide = 0, size = 0, rva = 0, relocTide = 0, numRelocs = 0;
  34. uint relocOff = 0, relocRVA = 0, lineRVA = 0, numLineNums = 0;
  35. uint flags = 0, padding = 0;
  36. uint[] relocs;
  37. //bool relocsDone = false;
  38. internal Section(string sName, uint sFlags)
  39. {
  40. nameString = sName;
  41. name = sName.ToCharArray();
  42. flags = sFlags;
  43. }
  44. internal Section(PEReader input)
  45. {
  46. name = new char[8];
  47. for (int i = 0; i < name.Length; i++)
  48. name[i] = (char)input.ReadByte();
  49. nameString = new String(name);
  50. tide = input.ReadUInt32();
  51. rva = input.ReadUInt32();
  52. size = input.ReadUInt32();
  53. offset = input.ReadUInt32();
  54. relocRVA = input.ReadUInt32();
  55. lineRVA = input.ReadUInt32();
  56. numRelocs = input.ReadUInt16();
  57. numLineNums = input.ReadUInt16();
  58. flags = input.ReadUInt32();
  59. if (Diag.DiagOn)
  60. {
  61. Console.WriteLine(" " + nameString + " RVA = " + Hex.Int(rva) + " vSize = " + Hex.Int(tide));
  62. Console.WriteLine(" FileOffset = " + Hex.Int(offset) + " aSize = " + Hex.Int(size));
  63. }
  64. }
  65. internal bool ContainsRVA(uint rvaPos)
  66. {
  67. return (rva <= rvaPos) && (rvaPos <= rva + tide);
  68. }
  69. internal uint GetOffset(uint inRVA)
  70. {
  71. uint offs = 0;
  72. if ((rva <= inRVA) && (inRVA <= rva + tide))
  73. offs = offset + (inRVA - rva);
  74. return offs;
  75. }
  76. internal uint Tide() { return tide; }
  77. internal void IncTide(uint incVal) { tide += incVal; }
  78. internal uint Padding() { return padding; }
  79. internal uint Size() { return size; }
  80. internal void SetSize(uint pad)
  81. {
  82. padding = pad;
  83. size = tide + padding;
  84. }
  85. internal uint RVA() { return rva; }
  86. internal void SetRVA(uint rva) { this.rva = rva; }
  87. internal uint Offset() { return offset; }
  88. internal void SetOffset(uint offs) { offset = offs; }
  89. internal void DoBlock(BinaryWriter reloc, uint page, int start, int end)
  90. {
  91. //Console.WriteLine("rva = " + rva + " page = " + page);
  92. if (Diag.DiagOn) Console.WriteLine("writing reloc block at " + reloc.BaseStream.Position);
  93. reloc.Write(rva + page);
  94. uint blockSize = (uint)(((end - start + 1) * 2) + 8);
  95. reloc.Write(blockSize);
  96. if (Diag.DiagOn) Console.WriteLine("Block size = " + blockSize);
  97. for (int j = start; j < end; j++)
  98. {
  99. //Console.WriteLine("reloc offset = " + relocs[j]);
  100. reloc.Write((ushort)((0x3 << 12) | (relocs[j] - page)));
  101. }
  102. reloc.Write((ushort)0);
  103. if (Diag.DiagOn) Console.WriteLine("finished reloc block at " + reloc.BaseStream.Position);
  104. }
  105. internal void DoRelocs(BinaryWriter reloc)
  106. {
  107. if (relocTide > 0)
  108. {
  109. // align block to 32 bit boundary
  110. relocOff = (uint)reloc.Seek(0, SeekOrigin.Current);
  111. if ((relocOff % 32) != 0)
  112. {
  113. uint padding = 32 - (relocOff % 32);
  114. for (int i = 0; i < padding; i++)
  115. reloc.Write((byte)0);
  116. relocOff += padding;
  117. }
  118. uint block = (relocs[0] / relocPageSize + 1) * relocPageSize;
  119. int start = 0;
  120. for (int i = 1; i < relocTide; i++)
  121. {
  122. if (relocs[i] >= block)
  123. {
  124. DoBlock(reloc, block - relocPageSize, start, i);
  125. start = i;
  126. block = (relocs[i] / relocPageSize + 1) * relocPageSize;
  127. }
  128. }
  129. DoBlock(reloc, block - relocPageSize, start, (int)relocTide);
  130. }
  131. }
  132. internal void AddReloc(uint offs)
  133. {
  134. if (Diag.DiagOn) Console.WriteLine("Adding a reloc to " + nameString + " section");
  135. int pos = 0;
  136. if (relocs == null)
  137. {
  138. relocs = new uint[5];
  139. }
  140. else
  141. {
  142. if (relocTide >= relocs.Length)
  143. {
  144. uint[] tmp = relocs;
  145. relocs = new uint[tmp.Length + 5];
  146. for (int i = 0; i < relocTide; i++)
  147. {
  148. relocs[i] = tmp[i];
  149. }
  150. }
  151. while ((pos < relocTide) && (relocs[pos] < offs)) pos++;
  152. for (int i = pos; i < relocTide; i++)
  153. {
  154. relocs[i + 1] = relocs[i];
  155. }
  156. }
  157. relocs[pos] = offs;
  158. relocTide++;
  159. if (Diag.DiagOn) Console.WriteLine("relocTide = " + relocTide);
  160. }
  161. internal void WriteHeader(BinaryWriter output, uint relocRVA)
  162. {
  163. if (Diag.DiagOn) Console.WriteLine("relocTide = " + relocTide);
  164. output.Write(name);
  165. output.Write(tide); // Virtual size
  166. output.Write(rva); // Virtual address
  167. output.Write(size); // SizeOfRawData
  168. output.Write(offset); // PointerToRawData
  169. if (relocTide > 0)
  170. {
  171. output.Write(relocRVA + relocOff);
  172. }
  173. else
  174. {
  175. if (Diag.DiagOn) Console.WriteLine(nameString + " section has no relocs");
  176. output.Write(0);
  177. } // PointerToRelocations
  178. output.Write(0); // PointerToLineNumbers
  179. output.Write((ushort)relocTide); // NumberOfRelocations
  180. output.Write((ushort)0); // NumberOfLineNumbers
  181. output.Write(flags); // Characteristics
  182. }
  183. }
  184. }