2
0

Debugging.Mod 7.0 KB

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