Debugging.Mod 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. MODULE Debugging; (** AUTHOR "fof"; PURPOSE "Debugging facilities"; **)
  2. IMPORT SYSTEM, Streams, KernelLog, Files, StringPool, Modules, Objects, Reflection, Machine, Commands, Locks, Dates, Heaps;
  3. VAR
  4. DefaultLog, Log-: Streams.Writer; f: Files.File; lock: Locks.RWLock;
  5. PROCEDURE Memory*( from, tov: ADDRESS );
  6. VAR i: ADDRESS; val: SIZE;
  7. BEGIN
  8. Log.String( ">>>>>" ); Log.Ln;
  9. IF from = 0 THEN Log.String( "NIL Region" ); Log.Ln; ELSE
  10. FOR i := from TO tov BY SIZEOF(ADDRESS) DO
  11. Log.Address( i ); Log.String( "H (" ); Log.Int( i, 0 );
  12. Log.String( "," ); Log.Int( i - from, 4 ); Log.String( ") " );
  13. SYSTEM.GET( i, val ); Log.Address( val ); Log.String( "H = " );
  14. Log.Int( val, 10 ); Log.Ln;
  15. END;
  16. END;
  17. Log.String( "<<<<<" ); Log.Ln;
  18. Log.Update;
  19. END Memory;
  20. PROCEDURE ViewStack( ebp, esp: ADDRESS; CONST s: ARRAY OF CHAR);
  21. VAR i: ADDRESS; val: LONGINT; prevBP:ADDRESS;
  22. CONST adrSize= SIZEOF(ADDRESS);
  23. BEGIN
  24. Log.String( ">>>>> " ); Log.String(s); Log.String (" >>>>>> "); Log.Ln;
  25. SYSTEM.GET(ebp,prevBP);
  26. IF prevBP-ebp > 1024 THEN prevBP := ebp END;
  27. FOR i := prevBP TO esp BY -adrSize DO
  28. Log.Address( i ); Log.String( "H (" ); Log.Int( i, 0 ); Log.String( "," );
  29. Log.Int( i - ebp, 4 ); Log.String( ") " ); SYSTEM.GET( i, val );
  30. Log.Address( val ); Log.String( "H = " ); Log.Int( val, 10 );
  31. IF (i = prevBP) & (i # ebp) THEN Log.String(" <----- [EBP]"); END;
  32. IF i = ebp THEN Log.String(" <----- EBP"); END;
  33. IF i = ebp+adrSize THEN Log.String(" <----- EIP"); END;
  34. IF i = esp THEN Log.String(" <----- ESP"); END;
  35. Log.Ln;
  36. END;
  37. Log.String( "<<<<<" ); Log.Ln;
  38. Log.Update;
  39. END ViewStack;
  40. PROCEDURE Stack*(CONST s: ARRAY OF CHAR);
  41. VAR bp,oldbp: ADDRESS;
  42. BEGIN
  43. bp := Machine.CurrentBP();
  44. SYSTEM.GET(bp,oldbp);
  45. ViewStack(oldbp,bp+4*SIZEOF(ADDRESS),s);
  46. END Stack;
  47. PROCEDURE TraceBackThis( eip, ebp: ADDRESS; stacklow, stackhigh:ADDRESS ); (* do a stack trace back w.r.t. given instruction and frame pointers *)
  48. BEGIN
  49. Log.Ln; Log.String( "#######################" );
  50. Log.Ln; Log.String( "# Debugging.TraceBack #" );
  51. Log.Ln; Log.String( "#######################" );
  52. Log.Ln; Reflection.StackTraceBack( Log, eip, ebp, stacklow, stackhigh, TRUE , FALSE );
  53. Log.Update;
  54. END TraceBackThis;
  55. PROCEDURE TraceBack*; (* do a stack trace back starting at the calling instruction position *)
  56. BEGIN
  57. Enter;
  58. TraceBackThis( Machine.CurrentPC(), Machine.CurrentBP(), Machine.CurrentSP(), Objects.GetStackBottom(Objects.CurrentProcess()) );
  59. Exit;
  60. END TraceBack;
  61. (* TraceBackAll implemented in System.ShowStacks *)
  62. PROCEDURE FileStart*(context: Commands.Context); (* start writing to a the file Debugging.Text *)
  63. VAR w: Files.Writer; filename: ARRAY 256 OF CHAR;
  64. BEGIN
  65. IF context # NIL THEN
  66. context.arg.String(filename);
  67. ELSE
  68. filename := ""
  69. END;
  70. IF (filename = "") THEN filename := "Debugging.Text" END;
  71. KernelLog.String("filename = "); KernelLog.String(filename); KernelLog.String("<"); KernelLog.Ln;
  72. f := Files.New( filename );
  73. Files.OpenWriter( w, f, 0 );
  74. Log := w
  75. END FileStart;
  76. PROCEDURE FileEnd*; (* stop writing to Debugging.Text *)
  77. BEGIN
  78. Log.Update; Files.Register( f ); f.Update; f := NIL; Log := DefaultLog;
  79. END FileEnd;
  80. (* shortcut for String, usage deprecated *)
  81. PROCEDURE Str*( CONST name: ARRAY OF CHAR );
  82. BEGIN
  83. Log.String( name );
  84. END Str;
  85. PROCEDURE String*(CONST name: ARRAY OF CHAR);
  86. BEGIN
  87. Log.String(name);
  88. END String;
  89. PROCEDURE Address*(i: ADDRESS);
  90. BEGIN
  91. Log.Address(i);
  92. END Address;
  93. PROCEDURE Int*( i,j: LONGINT );
  94. BEGIN
  95. Log.Int( i, j );
  96. END Int;
  97. PROCEDURE Set*(set: SET);
  98. VAR i: LONGINT; first: BOOLEAN;
  99. BEGIN
  100. Log.String("{"); first := TRUE;
  101. FOR i := MIN(SET) TO MAX(SET) DO
  102. IF i IN set THEN
  103. IF first THEN first := FALSE ELSE Log.String(",") END;
  104. Log.Int(i,1)
  105. END;
  106. END;
  107. Log.String("}");
  108. END Set;
  109. PROCEDURE Float*( r: LONGREAL; len: LONGINT );
  110. BEGIN
  111. Log.Float( r, len );
  112. END Float;
  113. PROCEDURE Hex*( i: HUGEINT; j: LONGINT );
  114. BEGIN
  115. Log.Hex( i, j );
  116. END Hex;
  117. PROCEDURE HIntHex*( x: HUGEINT );
  118. BEGIN
  119. Hex( SHORT( ASH( x, -32 ) ),1 ); Hex( SHORT( x ),1 )
  120. END HIntHex;
  121. PROCEDURE Char*( c: CHAR );
  122. BEGIN
  123. Log.Char( c );
  124. END Char;
  125. PROCEDURE Update*;
  126. BEGIN
  127. Log.Update;
  128. END Update;
  129. PROCEDURE Ln*;
  130. BEGIN
  131. Log.Ln; Update;
  132. END Ln;
  133. PROCEDURE Type*( p: ANY ); (* output the type name of object pointed to by p *)
  134. VAR t: Modules.TypeDesc;
  135. BEGIN
  136. IF p = NIL THEN Str( "NIL (no type)" )
  137. ELSE
  138. t := Modules.TypeOf( p );
  139. IF t = NIL THEN Str( "unknown" ) ELSE Str( t.mod.name ); Str( "." ); Str( t.name ); END;
  140. END;
  141. END Type;
  142. PROCEDURE Str0*( idx: StringPool.Index ); (* output string index as string *)
  143. VAR name: ARRAY 256 OF CHAR;
  144. BEGIN
  145. StringPool.GetString( idx, name ); Log.String( name );
  146. END Str0;
  147. PROCEDURE Enter*; (* start exclusive writing *)
  148. VAR a: ANY; p: Objects.Process; dt: Dates.DateTime;
  149. BEGIN
  150. lock.AcquireWrite; Ln;
  151. Str( "{ [P " ); p := Objects.CurrentProcess(); Int( p.id,1 ); Str( " " ); a := Objects.ActiveObject(); Type( a ); Str( "] " );
  152. dt := Dates.Now(); Int(dt.hour,0); Char(':'); Int(dt.minute,0); Char(':'); Int(dt.second,0);
  153. END Enter;
  154. PROCEDURE Exit*; (* end exclusive writing *)
  155. BEGIN
  156. Str( "}" ); Log.Update; lock.ReleaseWrite;
  157. END Exit;
  158. PROCEDURE Nothing;
  159. BEGIN
  160. END Nothing;
  161. PROCEDURE Halt*;
  162. BEGIN HALT (1234);
  163. END Halt;
  164. PROCEDURE DisableGC*;
  165. BEGIN
  166. Heaps.GC := Nothing;
  167. TRACE(Heaps.GC, "disabled");
  168. END DisableGC;
  169. PROCEDURE EnableGC*;
  170. BEGIN
  171. Heaps.GC := Heaps.InvokeGC;
  172. TRACE(Heaps.GC, "enabled");
  173. END EnableGC;
  174. (* useful for debugging the GC / metadata *)
  175. PROCEDURE ReportProcedureDescriptors*;
  176. VAR m: Modules.Module; i,j: LONGINT;
  177. BEGIN
  178. m := Modules.root;
  179. WHILE (m # NIL) DO
  180. TRACE(m.name);
  181. IF m.procTable # NIL THEN
  182. FOR i := 0 TO LEN(m.procTable)-1 DO
  183. (*TRACE(m.procTable[i]);*)
  184. Log.Address(m.procTable[i]);
  185. Log.String(":");
  186. Reflection.WriteProc(Log, m.procTable[i].pcFrom);
  187. Log.String(" ptrs @ ");
  188. FOR j := 0 TO LEN(m.procTable[i].offsets)-1 DO
  189. Log.Int(m.procTable[i].offsets[j],1);
  190. Log.String(" ");
  191. END;
  192. Log.Ln;
  193. END;
  194. END;
  195. m := m.next;
  196. END;
  197. END ReportProcedureDescriptors;
  198. PROCEDURE ReportModule* (context: Commands.Context);
  199. VAR m: Modules.Module; name: Modules.Name;
  200. BEGIN
  201. IF ~context.arg.GetString (name) THEN
  202. context.result := Commands.CommandParseError;
  203. RETURN;
  204. END;
  205. m := Modules.root;
  206. WHILE (m # NIL) DO
  207. IF m.name = name THEN
  208. Reflection.Report (context.out, m.refs, 0);
  209. context.result := Commands.Ok;
  210. RETURN;
  211. END;
  212. m := m.next;
  213. END;
  214. context.result := Commands.CommandError;
  215. END ReportModule;
  216. BEGIN
  217. Streams.OpenWriter( DefaultLog, KernelLog.Send ); Log := DefaultLog; NEW( lock );
  218. END Debugging.
  219. System.FreeDownTo Debugging ~
  220. Debugging.ReportProcedureDescriptors