Debugger.hx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /*
  2. * Copyright (C)2005-2017 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. {
  30. public var name(default, null) : String;
  31. public var value(default, null) : Dynamic;
  32. public function new(name : String, value : Dynamic)
  33. {
  34. this.name = name;
  35. this.value = value;
  36. }
  37. }
  38. /**
  39. * StackFrame describes one call stack frame.
  40. **/
  41. class StackFrame
  42. {
  43. public var fileName(default, null) : String;
  44. public var lineNumber(default, null) : Int;
  45. public var className(default, null) : String;
  46. public var functionName(default, null) : String;
  47. public var parameters(default, null) : Array<Parameter>;
  48. public function new(fileName : String, lineNumber : Int,
  49. className : String, functionName : String)
  50. {
  51. this.fileName = fileName;
  52. this.lineNumber = lineNumber;
  53. this.className = className;
  54. this.functionName = functionName;
  55. this.parameters = new Array<Parameter>();
  56. }
  57. }
  58. /**
  59. * ThreadInfo describes the state of a single thread.
  60. **/
  61. class ThreadInfo
  62. {
  63. public static inline var STATUS_RUNNING = 1;
  64. public static inline var STATUS_STOPPED_BREAK_IMMEDIATE = 2;
  65. public static inline var STATUS_STOPPED_BREAKPOINT = 3;
  66. public static inline var STATUS_STOPPED_UNCAUGHT_EXCEPTION = 4;
  67. public static inline var STATUS_STOPPED_CRITICAL_ERROR = 5;
  68. // 0 is never a valid thread number
  69. public var number(default, null) : Int;
  70. public var status(default, null) : Int;
  71. // If status is "stopped breakpoint", this is the breakpoint number
  72. public var breakpoint(default, null) : Int;
  73. // If status is "critical error", this describes the error
  74. public var criticalErrorDescription(default, null) : String;
  75. // Stack will be listed with the lowest frame first
  76. public var stack(default, null) : Array<StackFrame>;
  77. public function new(number : Int, status : Int, breakpoint : Int = -1,
  78. criticalErrorDescription : String = null)
  79. {
  80. this.number = number;
  81. this.status = status;
  82. this.breakpoint = breakpoint;
  83. this.criticalErrorDescription = criticalErrorDescription;
  84. this.stack = new Array<StackFrame>();
  85. }
  86. }
  87. /**
  88. * This class wraps the hxcpp C++ implementation to provide a Haxe interface
  89. * to the low level debugging features
  90. **/
  91. class Debugger
  92. {
  93. public static inline var THREAD_CREATED = 1;
  94. public static inline var THREAD_TERMINATED = 2;
  95. public static inline var THREAD_STARTED = 3;
  96. public static inline var THREAD_STOPPED = 4;
  97. public static inline var STEP_INTO = 1;
  98. public static inline var STEP_OVER = 2;
  99. public static inline var STEP_OUT = 3;
  100. // This tagging value is returned by getStackVariableValue() and
  101. // setStackVariableValue if the requested value does not exist at the
  102. // requested stack frame
  103. public static var NONEXISTENT_VALUE = new String("NONEXISTENT_VALUE");
  104. // This tagging value is returned by getStackVariableValue and
  105. // setStackVariableValue if the stack variable that is being set is on a
  106. // thread that is running, in which case the set does not take place.
  107. public static var THREAD_NOT_STOPPED = new String("THREAD_NOT_STOPPED");
  108. /**
  109. * Sets the handler callback to be made when asynchronous events occur,
  110. * specifically, when threads are created, terminated, started, or
  111. * stopped. The calling thread becomes the "debugger" thread, which means
  112. * that it will be discluded from any breakpoints and will not be reported
  113. * on by any thread reporting requests.
  114. *
  115. * Be aware that this callback is made asynchronously and possibly by
  116. * multiple threads simultaneously.
  117. *
  118. * Setting this to null prevents further callbacks.
  119. *
  120. * Throws a string exception if the program does not support debugging
  121. * because it was not compiled with the HXCPP_DEBUGGER flag set.
  122. *
  123. * @param handler is a function that will be called back by asynchronous
  124. * thread events. Note that this function is called directly from
  125. * the thread experiencing the event and the handler should return
  126. * quickly to avoid blocking the calling thread unnecessarily.
  127. * The parameters to handler are:
  128. * - threadNumber, the thread number of the event
  129. * - event, one of THREAD_CREATED, THREAD_TERMINATED,
  130. * THREAD_STARTED, or THREAD_STOPPED
  131. * - stackFrame, the stack frame number at which the thread is stopped,
  132. * undefined if event is not THREAD_STOPPED
  133. * - className, the class name at which the thread is stopped,
  134. * undefined if event is not THREAD_STOPPED
  135. * - functionName, the function name at which the thread is
  136. * stopped, undefined if event is not THREAD_STOPPED
  137. * - fileName, the file name at which the thread is stopped,
  138. * undefined if event is not THREAD_STOPPED
  139. * - lineNumber, the line number at which the thread is stopped,
  140. * undefined if event is not THREAD_STOPPED
  141. **/
  142. public static function setEventNotificationHandler(
  143. handler : Int -> Int -> Int -> String -> String -> String -> Int -> Void)
  144. {
  145. untyped __global__.__hxcpp_dbg_setEventNotificationHandler(handler);
  146. }
  147. /**
  148. * This can be called to turn off (and then back on) all stopping of
  149. * debugged threads temporarily. It should only be used by classes that
  150. * actually implement the debugger to hide themselves from the debugger as
  151. * necessary.
  152. **/
  153. public static function enableCurrentThreadDebugging(enabled : Bool)
  154. {
  155. untyped __global__.__hxcpp_dbg_enableCurrentThreadDebugging(enabled);
  156. }
  157. /**
  158. * Returns the thread number of the calling thread.
  159. *
  160. * @return the thread number of the calling thread.
  161. **/
  162. public static function getCurrentThreadNumber() : Int
  163. {
  164. return untyped __global__.__hxcpp_dbg_getCurrentThreadNumber();
  165. }
  166. /**
  167. * Returns the set of source files known to the debugger. This is a copy
  168. * of the original array and could be quite large. The caller should
  169. * cache this value to avoid multiple copies needing to be made.
  170. *
  171. * @return the set of source files known to the debugger.
  172. **/
  173. public static function getFiles() : Array<String>
  174. {
  175. return untyped __global__.__hxcpp_dbg_getFiles();
  176. }
  177. /**
  178. * Returns the full paths of the set of source files known to the debugger.
  179. * This is a copy of the original array and could be quite large.
  180. * It is possible that this set will be empty, in which case the full paths are not known.
  181. * The index of these files matches the index from "getFiles", so the full path for
  182. * a given short path can be calculated.
  183. *
  184. * @return the known full paths of the set of source files
  185. **/
  186. public static function getFilesFullPath() : Array<String>
  187. {
  188. return untyped __global__.__hxcpp_dbg_getFilesFullPath();
  189. }
  190. /**
  191. * Returns the set of class names of all classes known to the debugger.
  192. * This is a copy of the original array and could be quite large. The
  193. * caller should cache this value to avoid multiple copies needing to be
  194. * made.
  195. *
  196. * @return the set of class names of all classes known to the debugger.
  197. **/
  198. public static function getClasses() : Array<String>
  199. {
  200. return untyped __global__.__hxcpp_dbg_getClasses();
  201. }
  202. /**
  203. * Returns a ThreadInfo object describing every thread that existed at the
  204. * moment that the call was made, except for the debugger thread.
  205. **/
  206. public static function getThreadInfos() : Array<ThreadInfo>
  207. {
  208. return untyped __global__.__hxcpp_dbg_getThreadInfos();
  209. }
  210. /**
  211. * Returns a ThreadInfo object describing a single thread, or null if
  212. * there is no such thread or the thread queried about was the debugger
  213. * thread and unsafe was not true.
  214. **/
  215. public static function getThreadInfo(threadNumber : Int,
  216. unsafe : Bool) : ThreadInfo
  217. {
  218. return untyped __global__.__hxcpp_dbg_getThreadInfo
  219. (threadNumber, unsafe);
  220. }
  221. /**
  222. * Adds a new file:line breakpoint. The breakpoint number of the newly
  223. * added breakpoint is returned.
  224. **/
  225. public static function addFileLineBreakpoint(file : String,
  226. line : Int) : Int
  227. {
  228. return untyped __global__.__hxcpp_dbg_addFileLineBreakpoint
  229. (file, line);
  230. }
  231. /**
  232. * Adds a new class:function breakpoint. The breakpoint number of the
  233. * newly added breakpoint is returned.
  234. **/
  235. public static function addClassFunctionBreakpoint(className : String,
  236. functionName : String) : Int
  237. {
  238. return untyped __global__.__hxcpp_dbg_addClassFunctionBreakpoint
  239. (className, functionName);
  240. }
  241. /**
  242. * Deletes a breakpoint, or all breakpoints.
  243. **/
  244. public static function deleteBreakpoint(number : Null<Int>)
  245. {
  246. if (number == null) {
  247. untyped __global__.__hxcpp_dbg_deleteAllBreakpoints();
  248. }
  249. else {
  250. untyped __global__.__hxcpp_dbg_deleteBreakpoint
  251. (cast (number, Int));
  252. }
  253. }
  254. /**
  255. * Breaks all threads except the debugger thread (which should be the same
  256. * as the calling thread!).
  257. *
  258. * If `wait` is true, waits up to 2 seconds for all threads to be broken.
  259. * Threads which are in blocking system calls and cannot break after 2
  260. * seconds remain running when this function returns.
  261. **/
  262. public static function breakNow(wait : Bool = true)
  263. {
  264. untyped __global__.__hxcpp_dbg_breakNow(wait);
  265. }
  266. /**
  267. * Continue execution of all stopped threads. If specialThreadNumber
  268. * is a valid thread number, then it will be continued past
  269. * `continueCount` breakpoints instead of just 1 like all of the other
  270. * threads.
  271. **/
  272. public static function continueThreads(specialThreadNumber : Int,
  273. continueCount : Int)
  274. {
  275. untyped __global__.__hxcpp_dbg_continueThreads
  276. (specialThreadNumber, continueCount);
  277. }
  278. /**
  279. * Single steps the given thread.
  280. **/
  281. public static function stepThread(threadNumber : Int,
  282. stepType : Int,
  283. stepCount : Int = 1)
  284. {
  285. untyped __global__.__hxcpp_dbg_stepThread
  286. (threadNumber, stepType, stepCount);
  287. }
  288. /**
  289. * Returns the list of local variables (including "this", function
  290. * arguments, and local variables) visible to the given thread at the
  291. * given stack frame.
  292. *
  293. * Returns a list with a single entry, THREAD_NOT_STOPPED, if the
  294. * thread is not stopped and thus variables cannot be fetched and
  295. * unsafe is not true.
  296. *
  297. * @return the list of local variables (including "this", function
  298. * arguments, and local variables) visible to the given thread at
  299. * the given stack frame.
  300. **/
  301. public static function getStackVariables(threadNumber : Int,
  302. stackFrameNumber : Int,
  303. unsafe : Bool) : Array<String>
  304. {
  305. return untyped __global__.__hxcpp_dbg_getStackVariables
  306. (threadNumber, stackFrameNumber, unsafe, THREAD_NOT_STOPPED);
  307. }
  308. /**
  309. * Returns the value of a stack variable, or NONEXISTENT_VALUE if the
  310. * requested value does not exist. If the thread is actively running
  311. * and unsafe is not true, returns THREAD_NOT_STOPPED.
  312. **/
  313. public static function getStackVariableValue(threadNumber : Int,
  314. stackFrameNumber : Int,
  315. name : String,
  316. unsafe : Bool) : Dynamic
  317. {
  318. return untyped __global__.__hxcpp_dbg_getStackVariableValue
  319. (threadNumber, stackFrameNumber, name, unsafe, NONEXISTENT_VALUE,
  320. THREAD_NOT_STOPPED);
  321. }
  322. /**
  323. * Sets the value of a stack variable and returns that value. If the
  324. * variable does not exist, on the stack, this function returns
  325. * NONEXISTENT_VALUE. If the thread is actively running and unsafe is not
  326. * true, returns THREAD_NOT_STOPPED, and the value is not set.
  327. **/
  328. public static function setStackVariableValue(threadNumber : Int,
  329. stackFrameNumber : Int,
  330. name : String,
  331. value : Dynamic,
  332. unsafe : Bool) : Dynamic
  333. {
  334. return untyped __global__.__hxcpp_dbg_setStackVariableValue
  335. (threadNumber, stackFrameNumber, name, value, unsafe,
  336. NONEXISTENT_VALUE, THREAD_NOT_STOPPED);
  337. }
  338. // The hxcpp runtime calls back through these functions to create Haxe
  339. // objects as needed, which allows the C++ implementation code to create
  340. // Haxe objects without having to actually know the structure of those
  341. // objects
  342. private static function __init__()
  343. {
  344. untyped __global__.__hxcpp_dbg_setNewParameterFunction
  345. (
  346. function (name : String, value : Dynamic) : Dynamic {
  347. return new Parameter(name, value);
  348. }
  349. );
  350. untyped __global__.__hxcpp_dbg_setNewStackFrameFunction
  351. (
  352. function (fileName : String, lineNumber : Int,
  353. className : String, functionName : String)
  354. {
  355. return new StackFrame(fileName, lineNumber,
  356. className, functionName);
  357. }
  358. );
  359. untyped __global__.__hxcpp_dbg_setNewThreadInfoFunction
  360. (
  361. function (number : Int, status : Int, breakpoint : Int,
  362. criticalErrorDescription : String) : Dynamic {
  363. return new ThreadInfo(number, status, breakpoint,
  364. criticalErrorDescription);
  365. }
  366. );
  367. untyped __global__.__hxcpp_dbg_setAddParameterToStackFrameFunction
  368. (
  369. function(inStackFrame : Dynamic, inParameter : Dynamic) {
  370. var stackFrame : StackFrame = cast inStackFrame;
  371. var parameter : Parameter = cast inParameter;
  372. stackFrame.parameters.push(parameter);
  373. }
  374. );
  375. untyped __global__.__hxcpp_dbg_setAddStackFrameToThreadInfoFunction
  376. (
  377. function(inThreadInfo : Dynamic, inStackFrame : Dynamic) {
  378. var threadInfo : ThreadInfo = cast inThreadInfo;
  379. var stackFrame : StackFrame = cast inStackFrame;
  380. threadInfo.stack.push(stackFrame);
  381. }
  382. );
  383. }
  384. }