LineNumberTable.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Mono.CompilerServices.SymbolWriter
  4. {
  5. public class LineNumberTable
  6. {
  7. public const int Default_LineBase = -1;
  8. public const int Default_LineRange = 8;
  9. public const byte Default_OpcodeBase = 9;
  10. public const bool SuppressDuplicates = true;
  11. public const byte DW_LNS_copy = 1;
  12. public const byte DW_LNS_advance_pc = 2;
  13. public const byte DW_LNS_advance_line = 3;
  14. public const byte DW_LNS_set_file = 4;
  15. public const byte DW_LNS_const_add_pc = 8;
  16. public const byte DW_LNE_end_sequence = 1;
  17. public const byte DW_LNE_MONO_negate_is_hidden = 64;
  18. internal const byte DW_LNE_MONO__extensions_start = 64;
  19. internal const byte DW_LNE_MONO__extensions_end = 127;
  20. protected LineNumberEntry[] _line_numbers;
  21. public readonly int LineBase;
  22. public readonly int LineRange;
  23. public readonly byte OpcodeBase;
  24. public readonly int MaxAddressIncrement;
  25. public LineNumberEntry[] LineNumbers
  26. {
  27. get
  28. {
  29. return this._line_numbers;
  30. }
  31. }
  32. protected LineNumberTable(MonoSymbolFile file)
  33. {
  34. this.LineBase = file.OffsetTable.LineNumberTable_LineBase;
  35. this.LineRange = file.OffsetTable.LineNumberTable_LineRange;
  36. this.OpcodeBase = (byte)file.OffsetTable.LineNumberTable_OpcodeBase;
  37. this.MaxAddressIncrement = (int)(255 - this.OpcodeBase) / this.LineRange;
  38. }
  39. internal LineNumberTable(MonoSymbolFile file, LineNumberEntry[] lines) : this(file)
  40. {
  41. this._line_numbers = lines;
  42. }
  43. //internal void Write(MonoSymbolFile file, MyBinaryWriter bw)
  44. //{
  45. // int start = (int)bw.BaseStream.Position;
  46. // bool last_is_hidden = false;
  47. // int last_line = 1;
  48. // int last_offset = 0;
  49. // int last_file = 1;
  50. // int i = 0;
  51. // while (i < this.LineNumbers.Length)
  52. // {
  53. // int line_inc = this.LineNumbers[i].Row - last_line;
  54. // int offset_inc = this.LineNumbers[i].Offset - last_offset;
  55. // if (i + 1 >= this.LineNumbers.Length)
  56. // {
  57. // goto IL_84;
  58. // }
  59. // if (!this.LineNumbers[i + 1].Equals(this.LineNumbers[i]))
  60. // {
  61. // goto IL_84;
  62. // }
  63. // IL_207:
  64. // i++;
  65. // continue;
  66. // IL_84:
  67. // if (this.LineNumbers[i].File != last_file)
  68. // {
  69. // bw.Write(4);
  70. // bw.WriteLeb128(this.LineNumbers[i].File);
  71. // last_file = this.LineNumbers[i].File;
  72. // }
  73. // if (this.LineNumbers[i].IsHidden != last_is_hidden)
  74. // {
  75. // bw.Write(0);
  76. // bw.Write(1);
  77. // bw.Write(64);
  78. // last_is_hidden = this.LineNumbers[i].IsHidden;
  79. // }
  80. // if (offset_inc >= this.MaxAddressIncrement)
  81. // {
  82. // if (offset_inc < 2 * this.MaxAddressIncrement)
  83. // {
  84. // bw.Write(8);
  85. // offset_inc -= this.MaxAddressIncrement;
  86. // }
  87. // else
  88. // {
  89. // bw.Write(2);
  90. // bw.WriteLeb128(offset_inc);
  91. // offset_inc = 0;
  92. // }
  93. // }
  94. // if (line_inc < this.LineBase || line_inc >= this.LineBase + this.LineRange)
  95. // {
  96. // bw.Write(3);
  97. // bw.WriteLeb128(line_inc);
  98. // if (offset_inc != 0)
  99. // {
  100. // bw.Write(2);
  101. // bw.WriteLeb128(offset_inc);
  102. // }
  103. // bw.Write(1);
  104. // }
  105. // else
  106. // {
  107. // byte opcode = (byte)(line_inc - this.LineBase + this.LineRange * offset_inc + (int)this.OpcodeBase);
  108. // bw.Write(opcode);
  109. // }
  110. // last_line = this.LineNumbers[i].Row;
  111. // last_offset = this.LineNumbers[i].Offset;
  112. // goto IL_207;
  113. // }
  114. // bw.Write(0);
  115. // bw.Write(1);
  116. // bw.Write(1);
  117. // file.ExtendedLineNumberSize += (int)bw.BaseStream.Position - start;
  118. //}
  119. internal static LineNumberTable Read(MonoSymbolFile file, MyBinaryReader br)
  120. {
  121. LineNumberTable lnt = new LineNumberTable(file);
  122. lnt.DoRead(file, br);
  123. return lnt;
  124. }
  125. private void DoRead(MonoSymbolFile file, MyBinaryReader br)
  126. {
  127. List<LineNumberEntry> lines = new List<LineNumberEntry>();
  128. bool is_hidden = false;
  129. bool modified = false;
  130. int stm_line = 1;
  131. int stm_offset = 0;
  132. int stm_file = 1;
  133. byte opcode;
  134. while (true)
  135. {
  136. opcode = br.ReadByte();
  137. if (opcode == 0)
  138. {
  139. byte size = br.ReadByte();
  140. long end_pos = br.BaseStream.Position + (long)((ulong)size);
  141. opcode = br.ReadByte();
  142. if (opcode == 1)
  143. {
  144. break;
  145. }
  146. if (opcode == 64)
  147. {
  148. is_hidden = !is_hidden;
  149. modified = true;
  150. }
  151. else
  152. {
  153. if (opcode < 64 || opcode > 127)
  154. {
  155. goto IL_B8;
  156. }
  157. }
  158. br.BaseStream.Position = end_pos;
  159. }
  160. else
  161. {
  162. if (opcode < this.OpcodeBase)
  163. {
  164. switch (opcode)
  165. {
  166. case 1:
  167. lines.Add(new LineNumberEntry(stm_file, stm_line, stm_offset, is_hidden));
  168. modified = false;
  169. continue;
  170. case 2:
  171. stm_offset += br.ReadLeb128();
  172. modified = true;
  173. continue;
  174. case 3:
  175. stm_line += br.ReadLeb128();
  176. modified = true;
  177. continue;
  178. case 4:
  179. stm_file = br.ReadLeb128();
  180. modified = true;
  181. continue;
  182. case 8:
  183. stm_offset += this.MaxAddressIncrement;
  184. modified = true;
  185. continue;
  186. }
  187. goto Block_8;
  188. }
  189. opcode -= this.OpcodeBase;
  190. stm_offset += (int)opcode / this.LineRange;
  191. stm_line += this.LineBase + (int)opcode % this.LineRange;
  192. lines.Add(new LineNumberEntry(stm_file, stm_line, stm_offset, is_hidden));
  193. modified = false;
  194. }
  195. }
  196. if (modified)
  197. {
  198. lines.Add(new LineNumberEntry(stm_file, stm_line, stm_offset, is_hidden));
  199. }
  200. this._line_numbers = new LineNumberEntry[lines.Count];
  201. lines.CopyTo(this._line_numbers, 0);
  202. return;
  203. IL_B8:
  204. throw new MonoSymbolFileException("Unknown extended opcode {0:x} in LNT ({1})", new object[]
  205. {
  206. opcode,
  207. file.FileName
  208. });
  209. Block_8:
  210. throw new MonoSymbolFileException("Unknown standard opcode {0:x} in LNT", new object[]
  211. {
  212. opcode
  213. });
  214. }
  215. public bool GetMethodBounds(out LineNumberEntry start, out LineNumberEntry end)
  216. {
  217. bool result;
  218. if (this._line_numbers.Length > 1)
  219. {
  220. start = this._line_numbers[0];
  221. end = this._line_numbers[this._line_numbers.Length - 1];
  222. result = true;
  223. }
  224. else
  225. {
  226. start = LineNumberEntry.Null;
  227. end = LineNumberEntry.Null;
  228. result = false;
  229. }
  230. return result;
  231. }
  232. }
  233. }