Debugger.hx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. /*
  2. * Copyright (C)2005-2019 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package cpp.vm;
  23. /**
  24. * Parameter describes a function parameter. Instances of this class are
  25. * embedded in stack frame objects to describe the function parameters that
  26. * were used in the invocation of the function that defines that stack frame.
  27. **/
  28. class Parameter {
  29. public var name(default, null):String;
  30. public var value(default, null):Dynamic;
  31. public function new(name:String, value:Dynamic) {
  32. this.name = name;
  33. this.value = value;
  34. }
  35. }
  36. /**
  37. * StackFrame describes one call stack frame.
  38. **/
  39. class StackFrame {
  40. public var fileName(default, null):String;
  41. public var lineNumber(default, null):Int;
  42. public var className(default, null):String;
  43. public var functionName(default, null):String;
  44. public var parameters(default, null):Array<Parameter>;
  45. public function new(fileName:String, lineNumber:Int, className:String, functionName:String) {
  46. this.fileName = fileName;
  47. this.lineNumber = lineNumber;
  48. this.className = className;
  49. this.functionName = functionName;
  50. this.parameters = new Array<Parameter>();
  51. }
  52. }
  53. /**
  54. * ThreadInfo describes the state of a single thread.
  55. **/
  56. class ThreadInfo {
  57. public static inline var STATUS_RUNNING = 1;
  58. public static inline var STATUS_STOPPED_BREAK_IMMEDIATE = 2;
  59. public static inline var STATUS_STOPPED_BREAKPOINT = 3;
  60. public static inline var STATUS_STOPPED_UNCAUGHT_EXCEPTION = 4;
  61. public static inline var STATUS_STOPPED_CRITICAL_ERROR = 5;
  62. // 0 is never a valid thread number
  63. public var number(default, null):Int;
  64. public var status(default, null):Int;
  65. // If status is "stopped breakpoint", this is the breakpoint number
  66. public var breakpoint(default, null):Int;
  67. // If status is "critical error", this describes the error
  68. public var criticalErrorDescription(default, null):String;
  69. // Stack will be listed with the lowest frame first
  70. public var stack(default, null):Array<StackFrame>;
  71. public function new(number:Int, status:Int, breakpoint:Int = -1, criticalErrorDescription:String = null) {
  72. this.number = number;
  73. this.status = status;
  74. this.breakpoint = breakpoint;
  75. this.criticalErrorDescription = criticalErrorDescription;
  76. this.stack = new Array<StackFrame>();
  77. }
  78. }
  79. /**
  80. * This class wraps the hxcpp C++ implementation to provide a Haxe interface
  81. * to the low level debugging features
  82. **/
  83. class Debugger {
  84. public static inline var THREAD_CREATED = 1;
  85. public static inline var THREAD_TERMINATED = 2;
  86. public static inline var THREAD_STARTED = 3;
  87. public static inline var THREAD_STOPPED = 4;
  88. public static inline var STEP_INTO = 1;
  89. public static inline var STEP_OVER = 2;
  90. public static inline var STEP_OUT = 3;
  91. // This tagging value is returned by getStackVariableValue() and
  92. // setStackVariableValue if the requested value does not exist at the
  93. // requested stack frame
  94. public static var NONEXISTENT_VALUE = new String("NONEXISTENT_VALUE");
  95. // This tagging value is returned by getStackVariableValue and
  96. // setStackVariableValue if the stack variable that is being set is on a
  97. // thread that is running, in which case the set does not take place.
  98. public static var THREAD_NOT_STOPPED = new String("THREAD_NOT_STOPPED");
  99. /**
  100. * Sets the handler callback to be made when asynchronous events occur,
  101. * specifically, when threads are created, terminated, started, or
  102. * stopped. The calling thread becomes the "debugger" thread, which means
  103. * that it will be discluded from any breakpoints and will not be reported
  104. * on by any thread reporting requests.
  105. *
  106. * Be aware that this callback is made asynchronously and possibly by
  107. * multiple threads simultaneously.
  108. *
  109. * Setting this to null prevents further callbacks.
  110. *
  111. * Throws a string exception if the program does not support debugging
  112. * because it was not compiled with the HXCPP_DEBUGGER flag set.
  113. *
  114. * @param handler is a function that will be called back by asynchronous
  115. * thread events. Note that this function is called directly from
  116. * the thread experiencing the event and the handler should return
  117. * quickly to avoid blocking the calling thread unnecessarily.
  118. * The parameters to handler are:
  119. * - threadNumber, the thread number of the event
  120. * - event, one of THREAD_CREATED, THREAD_TERMINATED,
  121. * THREAD_STARTED, or THREAD_STOPPED
  122. * - stackFrame, the stack frame number at which the thread is stopped,
  123. * undefined if event is not THREAD_STOPPED
  124. * - className, the class name at which the thread is stopped,
  125. * undefined if event is not THREAD_STOPPED
  126. * - functionName, the function name at which the thread is
  127. * stopped, undefined if event is not THREAD_STOPPED
  128. * - fileName, the file name at which the thread is stopped,
  129. * undefined if event is not THREAD_STOPPED
  130. * - lineNumber, the line number at which the thread is stopped,
  131. * undefined if event is not THREAD_STOPPED
  132. **/
  133. public static function setEventNotificationHandler(handler:Int->Int->Int->String->String->String->Int->Void) {
  134. untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler);
  135. }
  136. /**
  137. * This can be called to turn off (and then back on) all stopping of
  138. * debugged threads temporarily. It should only be used by classes that
  139. * actually implement the debugger to hide themselves from the debugger as
  140. * necessary.
  141. **/
  142. public static function enableCurrentThreadDebugging(enabled:Bool) {
  143. untyped __global__.__hxcpp_dbg_enableCurrentThreadDebugging(enabled);
  144. }
  145. /**
  146. * Returns the thread number of the calling thread.
  147. *
  148. * @return the thread number of the calling thread.
  149. **/
  150. public static function getCurrentThreadNumber():Int {
  151. return untyped __global__.__hxcpp_dbg_getCurrentThreadNumber();
  152. }
  153. /**
  154. * Returns the set of source files known to the debugger. This is a copy
  155. * of the original array and could be quite large. The caller should
  156. * cache this value to avoid multiple copies needing to be made.
  157. *
  158. * @return the set of source files known to the debugger.
  159. **/
  160. public static function getFiles():Array<String> {
  161. return untyped __global__.__hxcpp_dbg_getFiles();
  162. }
  163. /**
  164. * Returns the full paths of the set of source files known to the debugger.
  165. * This is a copy of the original array and could be quite large.
  166. * It is possible that this set will be empty, in which case the full paths are not known.
  167. * The index of these files matches the index from "getFiles", so the full path for
  168. * a given short path can be calculated.
  169. *
  170. * @return the known full paths of the set of source files
  171. **/
  172. public static function getFilesFullPath():Array<String> {
  173. return untyped __global__.__hxcpp_dbg_getFilesFullPath();
  174. }
  175. /**
  176. * Returns the set of class names of all classes known to the debugger.
  177. * This is a copy of the original array and could be quite large. The
  178. * caller should cache this value to avoid multiple copies needing to be
  179. * made.
  180. *
  181. * @return the set of class names of all classes known to the debugger.
  182. **/
  183. public static function getClasses():Array<String> {
  184. return untyped __global__.__hxcpp_dbg_getClasses();
  185. }
  186. /**
  187. * Returns a ThreadInfo object describing every thread that existed at the
  188. * moment that the call was made, except for the debugger thread.
  189. **/
  190. public static function getThreadInfos():Array<ThreadInfo> {
  191. return untyped __global__.__hxcpp_dbg_getThreadInfos();
  192. }
  193. /**
  194. * Returns a ThreadInfo object describing a single thread, or null if
  195. * there is no such thread or the thread queried about was the debugger
  196. * thread and unsafe was not true.
  197. **/
  198. public static function getThreadInfo(threadNumber:Int, unsafe:Bool):ThreadInfo {
  199. return untyped __global__.__hxcpp_dbg_getThreadInfo(threadNumber, unsafe);
  200. }
  201. /**
  202. * Adds a new file:line breakpoint. The breakpoint number of the newly
  203. * added breakpoint is returned.
  204. **/
  205. public static function addFileLineBreakpoint(file:String, line:Int):Int {
  206. return untyped __global__.__hxcpp_dbg_addFileLineBreakpoint(file, line);
  207. }
  208. /**
  209. * Adds a new class:function breakpoint. The breakpoint number of the
  210. * newly added breakpoint is returned.
  211. **/
  212. public static function addClassFunctionBreakpoint(className:String, functionName:String):Int {
  213. return untyped __global__.__hxcpp_dbg_addClassFunctionBreakpoint(className, functionName);
  214. }
  215. /**
  216. * Deletes a breakpoint, or all breakpoints.
  217. **/
  218. public static function deleteBreakpoint(number:Null<Int>) {
  219. if (number == null) {
  220. untyped __global__.__hxcpp_dbg_deleteAllBreakpoints();
  221. } else {
  222. untyped __global__.__hxcpp_dbg_deleteBreakpoint(cast(number, Int));
  223. }
  224. }
  225. /**
  226. * Breaks all threads except the debugger thread (which should be the same
  227. * as the calling thread!).
  228. *
  229. * If `wait` is true, waits up to 2 seconds for all threads to be broken.
  230. * Threads which are in blocking system calls and cannot break after 2
  231. * seconds remain running when this function returns.
  232. **/
  233. public static function breakNow(wait:Bool = true) {
  234. untyped __global__.__hxcpp_dbg_breakNow(wait);
  235. }
  236. /**
  237. * Continue execution of all stopped threads. If specialThreadNumber
  238. * is a valid thread number, then it will be continued past
  239. * `continueCount` breakpoints instead of just 1 like all of the other
  240. * threads.
  241. **/
  242. public static function continueThreads(specialThreadNumber:Int, continueCount:Int) {
  243. untyped __global__.__hxcpp_dbg_continueThreads(specialThreadNumber, continueCount);
  244. }
  245. /**
  246. * Single steps the given thread.
  247. **/
  248. public static function stepThread(threadNumber:Int, stepType:Int, stepCount:Int = 1) {
  249. untyped __global__.__hxcpp_dbg_stepThread(threadNumber, stepType, stepCount);
  250. }
  251. /**
  252. * Returns the list of local variables (including "this", function
  253. * arguments, and local variables) visible to the given thread at the
  254. * given stack frame.
  255. *
  256. * Returns a list with a single entry, THREAD_NOT_STOPPED, if the
  257. * thread is not stopped and thus variables cannot be fetched and
  258. * unsafe is not true.
  259. *
  260. * @return the list of local variables (including "this", function
  261. * arguments, and local variables) visible to the given thread at
  262. * the given stack frame.
  263. **/
  264. public static function getStackVariables(threadNumber:Int, stackFrameNumber:Int, unsafe:Bool):Array<String> {
  265. return untyped __global__.__hxcpp_dbg_getStackVariables(threadNumber, stackFrameNumber, unsafe, THREAD_NOT_STOPPED);
  266. }
  267. /**
  268. * Returns the value of a stack variable, or NONEXISTENT_VALUE if the
  269. * requested value does not exist. If the thread is actively running
  270. * and unsafe is not true, returns THREAD_NOT_STOPPED.
  271. **/
  272. public static function getStackVariableValue(threadNumber:Int, stackFrameNumber:Int, name:String, unsafe:Bool):Dynamic {
  273. return untyped __global__.__hxcpp_dbg_getStackVariableValue(threadNumber, stackFrameNumber, name, unsafe, NONEXISTENT_VALUE, THREAD_NOT_STOPPED);
  274. }
  275. /**
  276. * Sets the value of a stack variable and returns that value. If the
  277. * variable does not exist, on the stack, this function returns
  278. * NONEXISTENT_VALUE. If the thread is actively running and unsafe is not
  279. * true, returns THREAD_NOT_STOPPED, and the value is not set.
  280. **/
  281. public static function setStackVariableValue(threadNumber:Int, stackFrameNumber:Int, name:String, value:Dynamic, unsafe:Bool):Dynamic {
  282. return untyped __global__.__hxcpp_dbg_setStackVariableValue(threadNumber, stackFrameNumber, name, value, unsafe, NONEXISTENT_VALUE,
  283. THREAD_NOT_STOPPED);
  284. }
  285. // The hxcpp runtime calls back through these functions to create Haxe
  286. // objects as needed, which allows the C++ implementation code to create
  287. // Haxe objects without having to actually know the structure of those
  288. // objects
  289. private static function __init__() {
  290. untyped __global__.__hxcpp_dbg_setNewParameterFunction(function(name:String, value:Dynamic):Dynamic {
  291. return new Parameter(name, value);
  292. });
  293. untyped __global__.__hxcpp_dbg_setNewStackFrameFunction(function(fileName:String, lineNumber:Int, className:String, functionName:String) {
  294. return new StackFrame(fileName, lineNumber, className, functionName);
  295. });
  296. untyped __global__.__hxcpp_dbg_setNewThreadInfoFunction(function(number:Int, status:Int, breakpoint:Int, criticalErrorDescription:String):Dynamic {
  297. return new ThreadInfo(number, status, breakpoint, criticalErrorDescription);
  298. });
  299. untyped __global__.__hxcpp_dbg_setAddParameterToStackFrameFunction(function(inStackFrame:Dynamic, inParameter:Dynamic) {
  300. var stackFrame:StackFrame = cast inStackFrame;
  301. var parameter:Parameter = cast inParameter;
  302. stackFrame.parameters.push(parameter);
  303. });
  304. untyped __global__.__hxcpp_dbg_setAddStackFrameToThreadInfoFunction(function(inThreadInfo:Dynamic, inStackFrame:Dynamic) {
  305. var threadInfo:ThreadInfo = cast inThreadInfo;
  306. var stackFrame:StackFrame = cast inStackFrame;
  307. threadInfo.stack.push(stackFrame);
  308. });
  309. }
  310. }