You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3326 lines
130 KiB

  1. -------------------------------------------------------------------------------
  2. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  3. -- All rights reserved. This program and the accompanying materials
  4. -- are made available under the terms of the Eclipse Public License v1.0
  5. -- which accompanies this distribution, and is available at
  6. -- http://www.eclipse.org/legal/epl-v10.html
  7. --
  8. -- Contributors:
  9. -- Sierra Wireless - initial API and implementation
  10. -------------------------------------------------------------------------------
  11. -- Debugger using DBGp protocol.
  12. -------------------------------------------------------------------------------
  13. -- The module returns a single init function which takes 6 parameters (IDEHOST, IDEPORT, IDEKEY, TRANSPORT, PLATFORM, WORKINGDIR).
  14. --
  15. -- IDEHOST: the host name or the ip address of the DBGP server (so your ide)
  16. -- if HOST is nil, the DBGP_IDEHOST env var is used.
  17. -- if the env var is nil, the default value '127.0.0.1' is used.
  18. --
  19. -- IDEPORT: the port of the DBGP server (must be configure in the IDE)
  20. -- if PORT is nil, the DBGP_IDEPORT env var is used.
  21. -- if the env var is nil, the default value '10000' is used.
  22. --
  23. -- IDEIDEKEY: a string which is used as session key
  24. -- if IDEKEY is nil, the DBGP_IDEKEY env var is used.
  25. -- if the env var is nil, the default value 'luaidekey' is used.
  26. --
  27. -- TRANSPORT: (advanced optional parameter) the module name of which implement the transport interface used to do the connection with the server.
  28. -- by default the debugger use an internal implementation based on luasocket, but if can not use it, you could implement or use another transport layer implementation.
  29. -- if TRANSPORT is nil, the DBGP_TRANSPORT env var is used.
  30. -- if the env var is nil, the default value 'debugger.transport.luasocket' is used : this is the default implementation based on luasocket.
  31. --
  32. -- PLATFORM: (advanced optional parameter) 'unix' or 'win32' string which define the kind of platform on which the program to debug is executed.
  33. -- by default the debugger will try to guess it and surely success, if for some reasons it fails you could help it by precise the execution platform.
  34. -- if PLATFORM is nil, the DBGP_PLATFORM env var is used.
  35. -- if the env var is nil, the debugger will try to guess it.
  36. --
  37. -- WORKINGDIR: (advanced optional parameter) the working directory in which the program to debug is executed.
  38. -- by default the debugger will try to guess it and surely success, if for some reasons it fails you could help it by precise the working directory.
  39. -- if WORKINGDIR is nil, the DBGP_WORKINGDIR env var is used.
  40. -- if the env var is nil, the debugger will try to guess it.
  41. --
  42. -------------------------------------------------------------------------------
  43. -- Known Issues:
  44. -- * Functions cannot be created using the debugger and then called in program because their environment is mapped directly to
  45. -- a debugger internal structure which cannot be persisted (i.e. used outside of the debug_hook).
  46. -- * The DLTK client implementation does not handle context for properties. As a workaround, the context is encoded into the
  47. -- fullname attribute of each property and is used likewise in property_get commands. The syntax is "<context ID>|<full name>"
  48. -- * Dynamic code (compiled with load or loadstring) is not handled (the debugger will step over it, like C code)
  49. -- Design notes:
  50. -- * The whole debugger state is kept in a (currently) unique session table in order to ease eventual adaptation to a multi-threaded
  51. -- model, as DBGp needs one connection per thread.
  52. -- * Full names of properties are base64 encoded because they can contain arbitrary data (spaces, escape characters, ...), this makes
  53. -- command parsing munch easier and faster
  54. -- * This debugger supports asynchronous commands: any command can be done at any time, but some of them (continuations) can lead to
  55. -- inconsistent states. In addition, this have a quite big overhead (~66%), if performance is an issue, a custom command to disable
  56. -- async mode could be done.
  57. -- * All commands are implemented in table commands, see this comments on this table to additional details about commands implementation
  58. -- * The environments in which are evaluated user code (property_* and eval commands, conditional breakpoints, ...) is a read/write
  59. -- mapping of the local environment of a given stack level (can be accessed with variable names). See Context for additional details.
  60. -- Context instantiation is pooled inside a debugging loop with ContextManager (each stack level is instantiated only once).
  61. -- * Output redirection is done by redefining print and some values inside the io table. See "Output redirection handling" for details.
  62. -- Todo list:
  63. -- * Override I/O in init function instead of on module loading.
  64. -- * Allow to break programatically (debugger.break()).
  65. -- * Break-on-error feature (break if an error is thrown and there is no pcall in stack to handle it).
  66. -- * Use new 5.2 facilities to provide informations about function (arguments names, vararg, ...)
  67. -- * Allow to see ... content for vararg functions (5.2 only)
  68. -- * Inspect LuaJIT C data (http://lua-users.org/lists/lua-l/2011-02/msg01012.html)-- /!\ This file is auto-generated. Do not alter manually /!\
  69. --------------------------------------------------------------------------------
  70. -- Submodules body
  71. --------------------------------------------------------------------------------
  72. --------------------------------------------------------------------------------
  73. -- Module debugger.transport.apr
  74. package.preload["debugger.transport.apr"] = function(...)
  75. -------------------------------------------------------------------------------
  76. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  77. -- All rights reserved. This program and the accompanying materials
  78. -- are made available under the terms of the Eclipse Public License v1.0
  79. -- which accompanies this distribution, and is available at
  80. -- http://www.eclipse.org/legal/epl-v10.html
  81. --
  82. -- Contributors:
  83. -- Sierra Wireless - initial API and implementation
  84. -------------------------------------------------------------------------------
  85. -- Apache Portable Runtime backend for DBGP debugger.
  86. -------------------------------------------------------------------------------
  87. local apr = require "apr"
  88. -- base 64 wrapping
  89. function b64_wrap(src)
  90. local t = {}
  91. local b64_src = mime.b64(src)
  92. for i=1, #b64_src, 76 do t[#t+1] = b64_src:sub(i, i+75).."\r\n" end
  93. return table.concat(t)
  94. end
  95. -- implements a subset of LuaSocket API using APR
  96. local SOCKET_MT = {
  97. connect = function(self, address, port) return self.skt:connect(address, port) end,
  98. receive = function(self, n) return self.skt:read(n) end, -- only numeric read is used
  99. send = function(self, data) return self.skt:write(data) end,
  100. close = function(self) return self.skt:close() end,
  101. settimeout = function(self, sec)
  102. if sec == nil then self.skt:timeout_set(true)
  103. elseif sec == 0 then self.skt:timeout_set(false)
  104. else self.skt:timeout_set(math.floor(sec * 1000000)) end
  105. end
  106. }
  107. SOCKET_MT.__index = SOCKET_MT
  108. return {
  109. create = function()
  110. local skt, err = apr.socket_create('tcp')
  111. if not skt then return nil, err end
  112. return setmetatable({skt = skt}, SOCKET_MT)
  113. end,
  114. sleep = apr.sleep, -- exact same API as LuaSocket
  115. -- Base64 related functions
  116. --- Encodes a string into Base64 with line wrapping
  117. -- @param data (string) data to encode
  118. -- @return base64 encoded string
  119. b64 = function(data)
  120. t = {}
  121. local b64_data = apr.base64_encode(data)
  122. for i=1, #b64_data, 76 do t[#t+1] = b64_data:sub(i, i+75).."\r\n" end
  123. return table.concat(t)
  124. end,
  125. --- Encodes a string into Base64, without any extra parsing (wrapping, ...)
  126. -- @param data (string) data to encode
  127. -- @return decoded string
  128. rawb64 = apr.base64_encode,
  129. --- Decodes base64 data
  130. -- @param data (string) base64 encoded data
  131. -- @return decoded string
  132. unb64 = apr.base64_decode,
  133. }
  134. end
  135. --------------------------------------------------------------------------------
  136. -- End of moduledebugger.transport.apr
  137. --------------------------------------------------------------------------------
  138. --------------------------------------------------------------------------------
  139. -- Module debugger.transport.luasocket
  140. package.preload["debugger.transport.luasocket"] = function(...)
  141. -------------------------------------------------------------------------------
  142. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  143. -- All rights reserved. This program and the accompanying materials
  144. -- are made available under the terms of the Eclipse Public License v1.0
  145. -- which accompanies this distribution, and is available at
  146. -- http://www.eclipse.org/legal/epl-v10.html
  147. --
  148. -- Contributors:
  149. -- Sierra Wireless - initial API and implementation
  150. -------------------------------------------------------------------------------
  151. -- LuaSocket backend for DBGP debugger.
  152. -------------------------------------------------------------------------------
  153. -- in order to be as lightweight as possible with Luasocket, core API is used
  154. -- directly (to no add yet another layer)
  155. --FIXME: remove this hack as soon as luasocket officially support 5.2
  156. if _VERSION == "Lua 5.2" then
  157. table.getn = function(t) return t and #t end
  158. end
  159. local socket = require "socket"
  160. local mime = require "mime"
  161. local ltn12 = require "ltn12"
  162. local reg = debug.getregistry()
  163. return {
  164. create = socket.tcp,
  165. sleep = socket.sleep,
  166. -- Base64 related functions
  167. --- Encodes a string into Base64 with line wrapping
  168. -- @param data (string) data to encode
  169. -- @return base64 encoded string
  170. b64 = function(data)
  171. local filter = ltn12.filter.chain(mime.encode("base64"), mime.wrap("base64"))
  172. local sink, output = ltn12.sink.table()
  173. ltn12.pump.all(ltn12.source.string(data), ltn12.sink.chain(filter, sink))
  174. return table.concat(output)
  175. end,
  176. --- Encodes a string into Base64, without any extra parsing (wrapping, ...)
  177. -- @param data (string) data to encode
  178. -- @return decoded string
  179. rawb64 = function(data)
  180. return (mime.b64(data)) -- first result of the low-level function is fine here
  181. end,
  182. --- Decodes base64 data
  183. -- @param data (string) base64 encoded data
  184. -- @return decoded string
  185. unb64 = function(data)
  186. return (mime.unb64(data)) -- first result of the low-level function is fine here
  187. end,
  188. }
  189. end
  190. --------------------------------------------------------------------------------
  191. -- End of moduledebugger.transport.luasocket
  192. --------------------------------------------------------------------------------
  193. --------------------------------------------------------------------------------
  194. -- Module debugger.transport.luasocket_sched
  195. package.preload["debugger.transport.luasocket_sched"] = function(...)
  196. -------------------------------------------------------------------------------
  197. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  198. -- All rights reserved. This program and the accompanying materials
  199. -- are made available under the terms of the Eclipse Public License v1.0
  200. -- which accompanies this distribution, and is available at
  201. -- http://www.eclipse.org/legal/epl-v10.html
  202. --
  203. -- Contributors:
  204. -- Sierra Wireless - initial API and implementation
  205. -------------------------------------------------------------------------------
  206. -- LuaSocket with LuaSched backend for DBGP debugger.
  207. -------------------------------------------------------------------------------
  208. -- As LuaShed totally hides blocking functions, this module MUST be loaded on the very start of the program
  209. -- (before loading sched) to catch references to blocking functions.
  210. local socketcore = require"socket.core"
  211. local debug = require "debug"
  212. local reg = debug.getregistry()
  213. local blockingcreate = socketcore.tcp
  214. local blockingsleep = socketcore.sleep
  215. local blockingconnect = reg["tcp{master}"].__index.connect
  216. local blockingreceive = reg["tcp{client}"].__index.receive
  217. local blockingsend = reg["tcp{client}"].__index.send
  218. local blockingsettimeout = reg["tcp{master}"].__index.settimeout
  219. local blockingclose = reg["tcp{master}"].__index.close
  220. -- we cannot set a new metatable directly on socket object, so wrap it into a new table
  221. -- and forward all calls.
  222. local blockingtcp = {
  223. connect = function(self, address, port) return blockingconnect(self.skt, address, port) end,
  224. receive = function(self, n) return blockingreceive(self.skt, n) end,
  225. send = function(self, data) return blockingsend(self.skt, data) end,
  226. settimeout = function(self, sec) return blockingsettimeout(self.skt, sec) end,
  227. close = function(self) return blockingclose(self.skt) end,
  228. }
  229. blockingtcp.__index = blockingtcp
  230. local mime = require "mime"
  231. local ltn12 = require "ltn12"
  232. -- verify that the socket function are the real ones and not sched not blocking versions
  233. assert(debug.getinfo(blockingcreate, "S").what == "C", "The debugger needs the real socket functions !")
  234. -- cleanup the package.loaded table (socket.core adds socket field into it)
  235. package.loaded.socket = nil
  236. return {
  237. create = function() return setmetatable({ skt = blockingcreate() }, blockingtcp) end,
  238. sleep = blockingsleep,
  239. -- Base64 related functions
  240. --- Encodes a string into Base64 with line wrapping
  241. -- @param data (string) data to encode
  242. -- @return base64 encoded string
  243. b64 = function(data)
  244. local filter = ltn12.filter.chain(mime.encode("base64"), mime.wrap("base64"))
  245. local sink, output = ltn12.sink.table()
  246. ltn12.pump.all(ltn12.source.string(data), ltn12.sink.chain(filter, sink))
  247. return table.concat(output)
  248. end,
  249. --- Encodes a string into Base64, without any extra parsing (wrapping, ...)
  250. -- @param data (string) data to encode
  251. -- @return decoded string
  252. rawb64 = function(data)
  253. return (mime.b64(data)) -- first result of the low-level function is fine here
  254. end,
  255. --- Decodes base64 data
  256. -- @param data (string) base64 encoded data
  257. -- @return decoded string
  258. unb64 = function(data)
  259. return (mime.unb64(data)) -- first result of the low-level function is fine here
  260. end,
  261. }
  262. end
  263. --------------------------------------------------------------------------------
  264. -- End of moduledebugger.transport.luasocket_sched
  265. --------------------------------------------------------------------------------
  266. --------------------------------------------------------------------------------
  267. -- Module debugger.commands
  268. package.preload["debugger.commands"] = function(...)
  269. -------------------------------------------------------------------------------
  270. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  271. -- All rights reserved. This program and the accompanying materials
  272. -- are made available under the terms of the Eclipse Public License v1.0
  273. -- which accompanies this distribution, and is available at
  274. -- http://www.eclipse.org/legal/epl-v10.html
  275. --
  276. -- Contributors:
  277. -- Sierra Wireless - initial API and implementation
  278. -------------------------------------------------------------------------------
  279. -- Commands handlers for DBGp protocol.
  280. -------------------------------------------------------------------------------
  281. -- Debugger command functions. Each function handle a different command.
  282. -- A command function is called with 3 arguments
  283. -- 1. the debug session instance
  284. -- 2. the command arguments as table
  285. -- 3. the command data, if any
  286. -- The result is either :
  287. -- * true (or any value evaluated to true) : the debugger will resume the execution of the application (continuation command)
  288. -- * false : only in async mode, the debugger WILL wait for further commands instead of continuing (typically, break command)
  289. -- * nil/no return : in sync mode, the debugger will wait for another command. In async mode the debugger will continue the execution
  290. local cowrap, coyield = coroutine.wrap, coroutine.yield
  291. local debug = require "debug"
  292. local core = require "debugger.core"
  293. local dbgp = require "debugger.dbgp"
  294. local util = require "debugger.util"
  295. local platform = require "debugger.platform"
  296. local introspection = require "debugger.introspection"
  297. local context = require "debugger.context"
  298. local log = util.log
  299. local M = { } -- command handlers table
  300. --- Gets the coroutine behind an id
  301. -- Throws errors on unknown identifiers
  302. -- @param coro_id (string or nil) Coroutine identifier or nil (current coroutine)
  303. -- @return Coroutine instance or nil (if coro_id was nil or if coroutine is the current coroutine)
  304. local function get_coroutine(self, coro_id)
  305. if coro_id then
  306. local coro = dbgp.assert(399, core.active_coroutines.from_id[tonumber(coro_id)], "No such coroutine")
  307. dbgp.assert(399, coroutine.status(coro) ~= "dead", "Coroutine is dead")
  308. if coro ~= self.coro[1] then return util.ForeignThread(coro) end
  309. end
  310. return self.coro
  311. end
  312. M["break"] = function(self, args)
  313. self.state = "break"
  314. -- send response to previous command
  315. core.previous_context_response(self)
  316. -- and then response to break command itself
  317. dbgp.send_xml(self.skt, { tag = "response", attr = { command = "break", transaction_id = args.i, success = 1 } } )
  318. return false
  319. end
  320. function M.status(self, args)
  321. dbgp.send_xml(self.skt, { tag = "response", attr = {
  322. command = "status",
  323. reason = "ok",
  324. status = self.state,
  325. transaction_id = args.i } } )
  326. end
  327. function M.stop(self, args)
  328. dbgp.send_xml(self.skt, { tag = "response", attr = {
  329. command = "stop",
  330. reason = "ok",
  331. status = "stopped",
  332. transaction_id = args.i } } )
  333. self.skt:close()
  334. os.exit(1)
  335. end
  336. function M.feature_get(self, args)
  337. local name = args.n
  338. local response = util.features[name] or (not not M[name])
  339. dbgp.send_xml(self.skt, { tag = "response", attr = {
  340. command = "feature_get",
  341. feature_name = name,
  342. supported = response and "1" or "0",
  343. transaction_id = args.i },
  344. tostring(response) } )
  345. end
  346. function M.feature_set(self, args)
  347. local name, value = args.n, args.v
  348. local success = pcall(function() util.features[name] = value end)
  349. dbgp.send_xml(self.skt, { tag = "response", attr = {
  350. command = "feature_set",
  351. feature = name,
  352. success = success and 1 or 0,
  353. transaction_id = args.i
  354. } } )
  355. end
  356. function M.typemap_get(self, args)
  357. local function gentype(name, type, xsdtype)
  358. return { tag = "map", atts = { name = name, type = type, ["xsi:type"] = xsdtype } }
  359. end
  360. dbgp.send_xml(self.skt, { tag = "response", attr = {
  361. command = "typemap_get",
  362. transaction_id = args.i,
  363. ["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance",
  364. ["xmlns:xsd"] = "http://www.w3.org/2001/XMLSchema",
  365. },
  366. gentype("nil", "null"),
  367. gentype("boolean", "bool", "xsd:boolean"),
  368. gentype("number", "float", "xsd:float"),
  369. gentype("string", "string", "xsd:string"),
  370. gentype("function", "resource"),
  371. gentype("userdata", "resource"),
  372. gentype("thread", "resource"),
  373. gentype("table", "hash"),
  374. gentype("sequence", "array"), -- artificial type to represent sequences (1-n continuous indexes)
  375. gentype("multival", "array"), -- used to represent return values
  376. } )
  377. end
  378. function M.run(self) return true end
  379. function M.step_over(self)
  380. core.events.register("over")
  381. return true
  382. end
  383. function M.step_out(self)
  384. core.events.register("out")
  385. return true
  386. end
  387. function M.step_into(self)
  388. core.events.register("into")
  389. return true
  390. end
  391. function M.eval(self, args, data)
  392. log("DEBUG", "Going to eval "..data)
  393. local result, err, success
  394. local env = self.stack(self.coro, 0)
  395. -- first, try to load as expression
  396. -- DBGp does not support stack level here, see http://bugs.activestate.com/show_bug.cgi?id=81178
  397. local func, err = util.loadin("return "..data, env)
  398. -- if it is not an expression, try as statement (assignment, ...)
  399. if not func then
  400. func, err = util.loadin(data, env)
  401. end
  402. if func then
  403. success, result = pcall(function() return introspection.Multival(func()) end)
  404. if not success then err = result end
  405. end
  406. local response = { tag = "response", attr = { command = "eval", transaction_id = args.i } }
  407. if not err then
  408. local nresults = result.n
  409. if nresults == 1 then result = result[1] end
  410. -- store result for further use (property_*)
  411. -- TODO: this could be optimized: this is only used for Expressions view and totally useless for interactive console,
  412. -- so storing result or not could be set by an argument
  413. local idx
  414. if nresults > 0 then
  415. local cache = env[context.Context[-1]]
  416. idx = #cache + 1
  417. cache[idx] = result
  418. end
  419. -- As of Lua 5.1, the maximum stack size (and result count) is 8000, this limit is used to fit all results in one page
  420. response[1] = introspection.make_property(-1, result, idx or "", nil, 1, 8000, 0, nil)
  421. response.attr.success = 1
  422. else
  423. response.attr.success = 0
  424. response[1] = dbgp.make_error(206, err)
  425. end
  426. dbgp.send_xml(self.skt, response)
  427. end
  428. function M.breakpoint_set(self, args, data)
  429. if args.o and not core.breakpoints.hit_conditions[args.o] then dbgp.error(200, "Invalid hit_condition operator: "..args.o) end
  430. local filename, lineno = args.f, tonumber(args.n)
  431. local bp = {
  432. type = args.t,
  433. state = args.s or "enabled",
  434. temporary = args.r == "1", -- "0" or nil makes this property false
  435. hit_count = 0,
  436. filename = filename,
  437. lineno = lineno,
  438. hit_value = tonumber(args.h or 0),
  439. hit_condition = args.o or ">=",
  440. }
  441. if args.t == "conditional" then
  442. bp.expression = data
  443. -- the expression is compiled only once
  444. bp.condition = dbgp.assert(207, loadstring("return (" .. data .. ")"))
  445. elseif args.t ~= "line" then dbgp.error(201, "BP type " .. args.t .. " not yet supported") end
  446. local bpid = core.breakpoints.insert(bp)
  447. dbgp.send_xml(self.skt, { tag = "response", attr = { command = "breakpoint_set", transaction_id = args.i, state = bp.state, id = bpid } } )
  448. end
  449. function M.breakpoint_get(self, args)
  450. dbgp.send_xml(self.skt, { tag = "response",
  451. attr = { command = "breakpoint_get", transaction_id = args.i },
  452. dbgp.assert(205, core.breakpoints.get_xml(tonumber(args.d))) })
  453. end
  454. function M.breakpoint_list(self, args)
  455. local bps = { tag = "response", attr = { command = "breakpoint_list", transaction_id = args.i } }
  456. for id, bp in pairs(core.breakpoints.get()) do bps[#bps + 1] = core.breakpoints.get_xml(id) end
  457. dbgp.send_xml(self.skt, bps)
  458. end
  459. function M.breakpoint_update(self, args)
  460. local bp = core.breakpoints.get(tonumber(args.d))
  461. if not bp then dbgp.error(205, "No such breakpint "..args.d) end
  462. if args.o and not core.breakpoints.hit_conditions[args.o] then dbgp.error(200, "Invalid hit_condition operator: "..args.o) end
  463. local response = { tag = "response", attr = { command = "breakpoint_update", transaction_id = args.i } }
  464. bp.state = args.s or bp.state
  465. bp.lineno = tonumber(args.n or bp.lineno)
  466. bp.hit_value = tonumber(args.h or bp.hit_value)
  467. bp.hit_condition = args.o or bp.hit_condition
  468. dbgp.send_xml(self.skt, response)
  469. end
  470. function M.breakpoint_remove(self, args)
  471. local response = { tag = "response", attr = { command = "breakpoint_remove", transaction_id = args.i } }
  472. if not core.breakpoints.remove(tonumber(args.d)) then dbgp.error(205, "No such breakpint "..args.d) end
  473. dbgp.send_xml(self.skt, response)
  474. end
  475. function M.stack_depth(self, args)
  476. local depth = 0
  477. local coro = get_coroutine(self, args.o)
  478. for level = 0, math.huge do
  479. local info = coro:getinfo(level, "St")
  480. if not info then break end -- end of stack
  481. depth = depth + 1
  482. if info.istailcall then depth = depth + 1 end -- a 'fake' level is added in that case
  483. if info.what == "main" then break end -- levels below main chunk are not interesting
  484. end
  485. dbgp.send_xml(self.skt, { tag = "response", attr = { command = "stack_depth", transaction_id = args.i, depth = depth} } )
  486. end
  487. function M.stack_get(self, args) -- TODO: dynamic code
  488. -- special URIs to identify unreachable stack levels
  489. local what2uri = {
  490. tail = "tailreturn:/",
  491. C = "ccode:/",
  492. }
  493. local function make_level(info, level)
  494. local attr = { level = level, where = info.name, type="file" }
  495. local uri = platform.get_uri(info.source)
  496. if uri and info.currentline then -- reachable level
  497. attr.filename = uri
  498. attr.lineno = info.currentline
  499. else
  500. attr.filename = what2uri[info.what] or "unknown:/"
  501. attr.lineno = -1
  502. end
  503. return { tag = "stack", attr = attr }
  504. end
  505. local node = { tag = "response", attr = { command = "stack_get", transaction_id = args.i} }
  506. local coro = get_coroutine(self, args.o)
  507. if args.d then
  508. local stack_level = tonumber(args.d)
  509. node[#node+1] = make_level(coro:getinfo(stack_level, "nSl"), stack_level)
  510. else
  511. for i=0, math.huge do
  512. local info = coro:getinfo(i, "nSlt")
  513. if not info then break end
  514. node[#node+1] = make_level(info, i)
  515. -- add a fake level of stack for tail calls (tells user that the function has not been called directly)
  516. if info.istailcall then
  517. node[#node+1] = { tag = "stack", attr = { level=i, type="file", filename="tailreturn:/", lineno=-1 } }
  518. end
  519. if info.what == "main" then break end -- levels below main chunk are not interesting
  520. end
  521. end
  522. dbgp.send_xml(self.skt, node)
  523. end
  524. --- Lists all active coroutines.
  525. -- Returns a list of active coroutines with their id (an arbitrary string) to query stack and properties. The id is
  526. -- guaranteed to be unique and stable for all coroutine life (they can be reused as long as coroutine exists).
  527. -- Others commands such as stack_get or property_* commands takes an additional -o switch to query a particular cOroutine.
  528. -- If the switch is not given, running coroutine will be used.
  529. -- In case of error on coroutines (most likely coroutine not found or dead), an error 399 is thrown.
  530. -- Note there is an important limitation due to Lua 5.1 coroutine implementation: you cannot query main "coroutine" from
  531. -- another one, so main coroutine is not in returned list (this will change with Lua 5.2).
  532. --
  533. -- This is a non-standard command. The returned XML has the following strucuture:
  534. -- <response command="coroutine_list" transaction_id="0">
  535. -- <coroutine name="<some printtable name>" id="<coroutine id>" running="0|1" />
  536. -- ...
  537. -- </response>
  538. function M.coroutine_list(self, args)
  539. local running = self.coro[1]
  540. local coroutines = { tag = "response", attr = { command = "coroutine_list", transaction_id = args.i } }
  541. -- as any operation on main coroutine will fail, it is not yet listed
  542. -- coroutines[1] = { name = "coroutine", attr = { id = 0, name = "main", running = (running == nil) and "1" or "0" } }
  543. for id, coro in pairs(core.active_coroutines.from_id) do
  544. if id ~= "n" then
  545. coroutines[#coroutines + 1] = { tag = "coroutine", attr = { id = id, name = tostring(coro), running = (coro == running) and "1" or "0" } }
  546. end
  547. end
  548. dbgp.send_xml(self.skt, coroutines)
  549. end
  550. function M.context_names(self, args)
  551. local coro = get_coroutine(self, args.o)
  552. local level = tonumber(args.d or 0)
  553. local info = coro:getinfo(level, "f") or dbgp.error(301, "No such stack level "..tostring(level))
  554. -- All contexts are always passed, even if empty. This is how DLTK expect context, what about others ?
  555. local contexts = {
  556. tag = "response", attr = { command = "context_names", transaction_id = args.i },
  557. { tag = "context", attr = { name = "Local", id = 0 } },
  558. { tag = "context", attr = { name = "Upvalue", id = 2 } },
  559. { tag = "context", attr = { name = "Global", id = 1 } },
  560. }
  561. dbgp.send_xml(self.skt, contexts)
  562. end
  563. function M.context_get(self, args)
  564. local cxt_num = tonumber(args.c or 0)
  565. local cxt_id = context.Context[cxt_num] or dbgp.error(302, "No such context: "..tostring(cxt_num))
  566. local level = tonumber(args.d or 0)
  567. local coro = get_coroutine(self, args.o)
  568. local cxt = self.stack(coro, level)
  569. local properties = { tag = "response", attr = { command = "context_get", transaction_id = args.i, context = context} }
  570. -- iteration over global is different (this could be unified in Lua 5.2 thanks to __pairs metamethod)
  571. for name, val in (cxt_num == 1 and next or getmetatable(cxt[cxt_id]).iterator), cxt[cxt_id], nil do
  572. -- the DBGp specification is not clear about the depth of a context_get, but a recursive get could be *really* slow in Lua
  573. properties[#properties + 1] = introspection.make_property(cxt_num, val, name, nil, 0, util.features.max_children, 0,
  574. util.features.max_data, cxt_num ~= 1)
  575. end
  576. dbgp.send_xml(self.skt, properties)
  577. end
  578. -------------------------------------------------------------------------------
  579. -- Property_* commands
  580. -------------------------------------------------------------------------------
  581. -- This in the environment in which properties are get or set.
  582. -- It notably contain a collection of proxy table which handle transparentely get/set operations on special fields
  583. -- and the cache of complex keys.
  584. local property_evaluation_environment = {
  585. key_cache = introspection.key_cache,
  586. metatable = setmetatable({ }, {
  587. __index = function(self, tbl) return getmetatable(tbl) end,
  588. __newindex = function(self, tbl, mt) return setmetatable(tbl, mt) end,
  589. }),
  590. environment = util.eval_env,
  591. }
  592. -- to allows to be set as metatable
  593. property_evaluation_environment.__index = property_evaluation_environment
  594. function M.property_get(self, args)
  595. --TODO BUG ECLIPSE TOOLSLINUX-99 352316
  596. local cxt_num, name = assert(util.unb64(args.n):match("^(%-?%d+)|(.*)$"))
  597. cxt_num = tonumber(args.c or cxt_num)
  598. local cxt_id = context.Context[cxt_num] or dbgp.error(302, "No such context: "..tostring(cxt_num))
  599. local level = tonumber(args.d or 0)
  600. local coro = get_coroutine(self, args.o)
  601. local size = tonumber(args.m or util.features.max_data)
  602. if size < 0 then size = nil end -- call from property_value
  603. local page = tonumber(args.p or 0)
  604. local cxt = self.stack(coro, level)
  605. local chunk = dbgp.assert(206, util.loadin("return "..name, property_evaluation_environment))
  606. local prop = select(2, dbgp.assert(300, pcall(chunk, cxt[cxt_id])))
  607. local response = introspection.make_property(cxt_num, prop, name, name, util.features.max_depth, util.features.max_children, page, size)
  608. -- make_property is not able to flag special variables as such when they are at root of property
  609. -- special variables queries are in the form "<proxy name>[(...)[a][b]<...>]"
  610. -- TODO: such parsing is far from perfect
  611. if name:match("^[%w_]+%[.-%b[]%]$") == name then response.attr.type = "special" end
  612. dbgp.send_xml(self.skt, { tag = "response",
  613. attr = { command = "property_get", transaction_id = args.i, context = context},
  614. response } )
  615. end
  616. function M.property_value(self, args)
  617. args.m = -1
  618. M.property_get(self, args)
  619. end
  620. function M.property_set(self, args, data)
  621. local cxt_num, name = assert(util.unb64(args.n):match("^(%-?%d+)|(.*)$"))
  622. cxt_num = tonumber(args.c or cxt_num)
  623. local cxt_id = context.Context[cxt_num] or dbgp.error(302, "No such context: "..tostring(cxt_num))
  624. local level = tonumber(args.d or 0)
  625. local coro = get_coroutine(self, args.o)
  626. local cxt = self.stack(coro, level)
  627. -- evaluate the new value in the local context
  628. local value = select(2, dbgp.assert(206, pcall(dbgp.assert(206, util.loadin("return "..data, cxt)))))
  629. local chunk = dbgp.assert(206, util.loadin(name .. " = value", setmetatable({ value = value }, property_evaluation_environment)))
  630. dbgp.assert(206, pcall(chunk, cxt[cxt_id]))
  631. dbgp.send_xml(self.skt, { tag = "response", attr = { success = 1, transaction_id = args.i } } )
  632. end
  633. --TODO dynamic code handling
  634. -- The DBGp specification is not clear about the line number meaning, this implementation is 1-based and numbers are inclusive
  635. function M.source(self, args)
  636. local path
  637. if args.f then
  638. path = platform.get_path(args.f)
  639. else
  640. path = self.coro:getinfo(0, "S").source
  641. assert(path:sub(1,1) == "@")
  642. path = path:sub(2)
  643. end
  644. local file, err = io.open(path)
  645. if not file then dbgp.error(100, err, { success = 0 }) end
  646. -- Try to identify compiled files
  647. if file:read(1) == "\033" then dbgp.error(100, args.f.." is bytecode", { success = 0 }) end
  648. file:seek("set", 0)
  649. local srclines = { }
  650. local beginline, endline, currentline = tonumber(args.b or 0), tonumber(args.e or math.huge), 0
  651. for line in file:lines() do
  652. currentline = currentline + 1
  653. if currentline >= beginline and currentline <= endline then
  654. srclines[#srclines + 1] = line
  655. elseif currentline >= endline then break end
  656. end
  657. file:close()
  658. srclines[#srclines + 1] = "" -- to add a trailing \n
  659. dbgp.send_xml(self.skt, { tag = "response",
  660. attr = { command = "source", transaction_id = args.i, success = 1},
  661. util.b64(table.concat(srclines, "\n")) })
  662. end
  663. -- Factory for both stdout and stderr commands, change file descriptor in io
  664. local function output_command_handler_factory(mode)
  665. return function(self, args)
  666. if args.c == "0" then -- disable
  667. io[mode] = io.base[mode]
  668. else
  669. io[mode] = setmetatable({ skt = self.skt, mode = mode }, args.c == "1" and core.copy_output or core.redirect_output)
  670. end
  671. dbgp.send_xml(self.skt, { tag = "response", attr = { command = mode, transaction_id = args.i, success = "1" } } )
  672. end
  673. end
  674. M.stdout = output_command_handler_factory("stdout")
  675. M.stderr = output_command_handler_factory("stderr")
  676. return M
  677. end
  678. --------------------------------------------------------------------------------
  679. -- End of moduledebugger.commands
  680. --------------------------------------------------------------------------------
  681. --------------------------------------------------------------------------------
  682. -- Module debugger.context
  683. package.preload["debugger.context"] = function(...)
  684. -------------------------------------------------------------------------------
  685. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  686. -- All rights reserved. This program and the accompanying materials
  687. -- are made available under the terms of the Eclipse Public License v1.0
  688. -- which accompanies this distribution, and is available at
  689. -- http://www.eclipse.org/legal/epl-v10.html
  690. --
  691. -- Contributors:
  692. -- Sierra Wireless - initial API and implementation
  693. -------------------------------------------------------------------------------
  694. -- Context handling: allows to evaluate code snippets in the context of a function
  695. -------------------------------------------------------------------------------
  696. local M = { }
  697. local dbgp = require "debugger.dbgp"
  698. local util = require "debugger.util"
  699. -- make unique object to access contexts
  700. local LOCAL, UPVAL, GLOBAL, EVAL, STORE, HANDLE = {}, {}, {}, {}, {}, {}
  701. local getglobals
  702. if _VERSION == "Lua 5.1" then
  703. getglobals = function(f) return getfenv(f) end
  704. elseif _VERSION == "Lua 5.2" then
  705. getglobals = function(f, cxt)
  706. -- 'global' environment: this is either the local _ENV or upvalue _ENV. A special case happen when a
  707. -- function does not reference any global variable: the upvalue _ENV may not exist at all. In this case,
  708. -- global environment is not relevant so it is fixed to an empty table. Another solution would be to set it
  709. -- to the environment from above stack level but it would require some overhead (especially if multiple
  710. -- levels must be instantiated)
  711. if cxt[LOCAL][STORE]["_ENV"] then return cxt[LOCAL]["_ENV"]
  712. elseif cxt[UPVAL][STORE]["_ENV"] then return cxt[UPVAL]["_ENV"]
  713. else return { } end
  714. end
  715. end
  716. --- Captures variables for given stack level. The capture contains local, upvalues and global variables.
  717. -- The capture can be seen as a proxy table to the stack level: any value can be queried or set no matter
  718. -- it is a local or an upvalue.
  719. -- The individual local and upvalues context are also available and can be queried and modified with indexed notation too.
  720. -- These objects are NOT persistant and must not be used outside the debugger loop which instanciated them !
  721. M.Context = {
  722. -- Context identifiers can be accessed by their DBGp context ID
  723. [0] = LOCAL,
  724. [1] = GLOBAL, -- DLTK internal ID for globals is 1
  725. [2] = UPVAL,
  726. -- EVAL is used to keep results from eval in cache in order to browse or modify them, results are stored as sequence
  727. [-1] = EVAL,
  728. STORE = STORE,
  729. -- gets a variable by name with correct handling of Lua scope chain
  730. -- the or chain does not work here beacause __index metamethod would raise an error instead of returning nil
  731. __index = function(self, k)
  732. if self[LOCAL][STORE][k] then return self[LOCAL][k]
  733. elseif self[UPVAL][STORE][k] then return self[UPVAL][k]
  734. else return self[GLOBAL][k] end
  735. end,
  736. __newindex = function(self, k, v)
  737. if self[LOCAL][STORE][k] then self[LOCAL][k] = v
  738. elseif self[UPVAL][STORE][k] then self[UPVAL][k] = v
  739. else self[GLOBAL][k] = v end
  740. end,
  741. -- debug only !!
  742. __tostring = function(self)
  743. local buf = { "Locals: \n" }
  744. for k,v in pairs(self[LOCAL][STORE]) do
  745. buf[#buf+1] = "\t"..tostring(k).."("..tostring(v)..")="..tostring(self[LOCAL][k]).."\n"
  746. end
  747. buf[#buf+1] = "Upvalues: \n"
  748. for k,v in pairs(self[UPVAL][STORE]) do
  749. buf[#buf+1] = "\t"..tostring(k).."("..tostring(v)..")="..tostring(self[UPVAL][k]).."\n"
  750. end
  751. return table.concat(buf)
  752. end,
  753. LocalContext = {
  754. __index = function(self, k)
  755. local index = self[STORE][k]
  756. if not index then error("The local "..tostring(k).." does not exists.") end
  757. local handle = self[HANDLE]
  758. return select(2, handle.coro:getlocal(handle.level, index))
  759. end,
  760. __newindex = function(self, k, v)
  761. local index = self[STORE][k]
  762. if index then
  763. local handle = self[HANDLE]
  764. handle.coro:setlocal(handle.level, index, v)
  765. else error("Cannot set local " .. k) end
  766. end,
  767. -- Lua 5.2 ready :)
  768. --__pairs = function(self) return getmetatable(self).iterator, self, nil end,
  769. iterator = function(self, prev)
  770. local key, index = next(self[STORE], prev)
  771. if key then return key, self[key] else return nil end
  772. end,
  773. },
  774. UpvalContext = {
  775. __index = function(self, k)
  776. local index = self[STORE][k]
  777. if not index then error("The local "..tostring(k).." does not exitsts.") end
  778. return select(2, debug.getupvalue(self[HANDLE], index))
  779. end,
  780. __newindex = function(self, k, v)
  781. local index = self[STORE][k]
  782. if index then debug.setupvalue(self[HANDLE], index, v)
  783. else error("Cannot set upvalue " .. k) end
  784. end,
  785. -- Lua 5.2 ready :)
  786. -- __pairs = function(self) return getmetatable(self).iterator, self, nil end,
  787. iterator = function(self, prev)
  788. local key, index = next(self[STORE], prev)
  789. if key then return key, self[key] else return nil end
  790. end,
  791. },
  792. --- Context constructor
  793. -- @param coro (util.*Thread instance) coroutine to map to
  794. -- @param level (number) stack level do dump (script stack level)
  795. new = function(cls, coro, level)
  796. local locals, upvalues = {}, {}
  797. if level < 0 then dbgp.error(301, "No such stack level: "..tostring(level)) end
  798. local func = (coro:getinfo(level, "f") or dbgp.error(301, "No such stack level: "..tostring(level))).func
  799. -- local variables
  800. for i=1, math.huge do
  801. local name, val = coro:getlocal(level, i)
  802. if not name then break
  803. elseif name:sub(1,1) ~= "(" then -- skip internal values
  804. locals[name] = i
  805. end
  806. end
  807. -- upvalues
  808. for i=1, math.huge do
  809. local name, val = debug.getupvalue(func, i)
  810. if not name then break end
  811. upvalues[name] = i
  812. end
  813. locals = setmetatable({ [STORE] = locals, [HANDLE] = { level = level, coro = coro } }, cls.LocalContext)
  814. upvalues = setmetatable({ [STORE] = upvalues, [HANDLE] = func }, cls.UpvalContext)
  815. local result = setmetatable({ [LOCAL] = locals, [UPVAL] = upvalues, [EVAL] = {} }, cls)
  816. rawset(result, GLOBAL, getglobals(func, result))
  817. return result
  818. end,
  819. }
  820. --- Handle caching of all instantiated context.
  821. -- Returns a function which takes 2 parameters: thread and stack level and returns the corresponding context. If this
  822. -- context has been already queried there is no new instantiation. A ContextManager is valid only during the debug loop
  823. -- on which it has been instantiated. References to a ContextManager must be lost after the end of debug loop (so
  824. -- threads can be collected).
  825. -- If a context cannot be instantiated, an 301 DBGP error is thrown.
  826. function M.ContextManager()
  827. local cache = { }
  828. return function(thread, level)
  829. -- the real coroutine is used as key (not the wrapped instance as its unicity is not guaranteed)
  830. -- otherwise, true is used to identify current thread (as nil is not a valid table key)
  831. local key = thread[1] or true
  832. local thread_contexts = cache[key]
  833. if not thread_contexts then
  834. thread_contexts = { }
  835. cache[key] = thread_contexts
  836. end
  837. local context = thread_contexts[level]
  838. if not context then
  839. context = M.Context:new(thread, level)
  840. thread_contexts[level] = context
  841. end
  842. return context
  843. end
  844. end
  845. return M
  846. end
  847. --------------------------------------------------------------------------------
  848. -- End of moduledebugger.context
  849. --------------------------------------------------------------------------------
  850. --------------------------------------------------------------------------------
  851. -- Module debugger.dbgp
  852. package.preload["debugger.dbgp"] = function(...)
  853. -------------------------------------------------------------------------------
  854. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  855. -- All rights reserved. This program and the accompanying materials
  856. -- are made available under the terms of the Eclipse Public License v1.0
  857. -- which accompanies this distribution, and is available at
  858. -- http://www.eclipse.org/legal/epl-v10.html
  859. --
  860. -- Contributors:
  861. -- Sierra Wireless - initial API and implementation
  862. -------------------------------------------------------------------------------
  863. -- DBGp protocol utility function (parsing, error handling, XML generation).
  864. -------------------------------------------------------------------------------
  865. local util = require "debugger.util"
  866. local error, setmetatable, type, pairs, ipairs, tostring, tconcat =
  867. error, setmetatable, type, pairs, ipairs, tostring, table.concat
  868. local M = { }
  869. --- Parses the DBGp command arguments and returns it as a Lua table with key/value pairs.
  870. -- For example, the sequence <code>-i 5 -j foo</code> will result in <code>{i=5, j=foo}</code>
  871. -- @param cmd_args (string) sequence of arguments
  872. -- @return table described above
  873. function M.arg_parse(cmd_args)
  874. local args = {}
  875. for arg, val in cmd_args:gmatch("%-(%w) (%S+)") do
  876. args[arg] = val
  877. end
  878. return args
  879. end
  880. --- Parses a command line
  881. -- @return commande name (string)
  882. -- @retrun arguments (table)
  883. -- @return data (string, optional)
  884. function M.cmd_parse(cmd)
  885. local cmd_name, args, data
  886. if cmd:find("--", 1, true) then -- there is a data part
  887. cmd_name, args, data = cmd:match("^(%S+)%s+(.*)%s+%-%-%s*(.*)$")
  888. data = util.unb64(data)
  889. else
  890. cmd_name, args = cmd:match("^(%S+)%s+(.*)$")
  891. end
  892. return cmd_name, M.arg_parse(args), data
  893. end
  894. --- Returns the packet read from socket, or nil followed by an error message on errors.
  895. function M.read_packet(skt)
  896. local size = {}
  897. while true do
  898. local byte, err = skt:receive(1)
  899. if not byte then return nil, err end
  900. if byte == "\000" then break end
  901. size[#size+1] = byte
  902. end
  903. return tconcat(size)
  904. end
  905. M.DBGP_ERR_METATABLE = {} -- unique object used to identify DBGp errors
  906. --- Throws a correct DBGp error which result in a fine tuned error message to the server.
  907. -- It is intended to be called into a command to make a useful error message, a standard Lua error
  908. -- result in a code 998 error (internal debugger error).
  909. -- @param code numerical error code
  910. -- @param message message string (optional)
  911. -- @param attr extra attributes to add to the response tag (optional)
  912. function M.error(code, message, attr)
  913. error(setmetatable({ code = code, message = message, attr = attr or {} }, M.DBGP_ERR_METATABLE), 2)
  914. end
  915. --- Like core assert but throws a DBGp error if condition is not met.
  916. -- @param code numerical error code thrown if condition is not met.
  917. -- @param message condition to test
  918. -- @param ... will be used as error message if test fails.
  919. function M.assert(code, success, ...)
  920. if not success then M.error(code, (...)) end
  921. return success, ...
  922. end
  923. -- -----------------
  924. -- Outgoing data
  925. -- -----------------
  926. local xmlattr_specialchars = { ['"'] = "&quot;", ["<"] = "&lt;", ["&"] = "&amp;" }
  927. --- Very basic XML generator
  928. -- Generates a XML string from a Lua Object Model (LOM) table.
  929. -- See http://matthewwild.co.uk/projects/luaexpat/lom.html
  930. function M.lom2str(xml)
  931. local pieces = { } -- string buffer
  932. local function generate(node)
  933. pieces[#pieces + 1] = "<"..node.tag
  934. pieces[#pieces + 1] = " "
  935. -- attribute ordering is not honored here
  936. for attr, val in pairs(node.attr or {}) do
  937. if type(attr) == "string" then
  938. pieces[#pieces + 1] = attr .. '="' .. tostring(val):gsub('["&<]', xmlattr_specialchars) .. '"'
  939. pieces[#pieces + 1] = " "
  940. end
  941. end
  942. pieces[#pieces] = nil -- remove the last separator (useless)
  943. if node[1] then
  944. pieces[#pieces + 1] = ">"
  945. for _, child in ipairs(node) do
  946. if type(child) == "table" then generate(child)
  947. else pieces[#pieces + 1] = "<![CDATA[" .. tostring(child) .. "]]>" end
  948. end
  949. pieces[#pieces + 1] = "</" .. node.tag .. ">"
  950. else
  951. pieces[#pieces + 1] = "/>"
  952. end
  953. end
  954. generate(xml)
  955. return tconcat(pieces)
  956. end
  957. function M.send_xml(skt, resp)
  958. if not resp.attr then resp.attr = {} end
  959. resp.attr.xmlns = "urn:debugger_protocol_v1"
  960. local data = '<?xml version="1.0" encoding="UTF-8" ?>\n'..M.lom2str(resp)
  961. util.log("DEBUG", "Send " .. data)
  962. skt:send(tostring(#data).."\000"..data.."\000")
  963. end
  964. --- Return an XML tag describing a debugger error, with an optional message
  965. -- @param code (number) error code (see DBGp specification)
  966. -- @param msg (string, optional) textual description of error
  967. -- @return table, suitable to be converted into XML
  968. function M.make_error(code, msg)
  969. local elem = { tag = "error", attr = { code = code } }
  970. if msg then
  971. elem[1] = { tostring(msg), tag = "message" }
  972. end
  973. return elem
  974. end
  975. return M
  976. end
  977. --------------------------------------------------------------------------------
  978. -- End of moduledebugger.dbgp
  979. --------------------------------------------------------------------------------
  980. --------------------------------------------------------------------------------
  981. -- Module debugger.introspection
  982. package.preload["debugger.introspection"] = function(...)
  983. -- ----------------------------------------------------------------------------
  984. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  985. -- All rights reserved. This program and the accompanying materials
  986. -- are made available under the terms of the Eclipse Public License v1.0
  987. -- which accompanies this distribution, and is available at
  988. -- http://www.eclipse.org/legal/epl-v10.html
  989. --
  990. -- Contributors:
  991. -- Julien Desgats - initial API and implementation
  992. -- ----------------------------------------------------------------------------
  993. -- Properties generation. Generate a LOM table with data from introspection.
  994. -- ----------------------------------------------------------------------------
  995. local debug = require "debug"
  996. local platform = require "debugger.platform"
  997. local util = require "debugger.util"
  998. local tostring, type, assert, next, rawget, getmetatable, setmetatable, getfenv, select, coyield, cocreate, costatus, coresume, sformat, tconcat =
  999. tostring, type, assert, next, rawget, getmetatable, setmetatable, getfenv, select, coroutine.yield, coroutine.create, coroutine.status, coroutine.resume, string.format, table.concat
  1000. local MULTIVAL_MT = { __tostring = function() return "" end }
  1001. local probes = { }
  1002. -- ---------- --
  1003. -- Public API --
  1004. -- ---------- --
  1005. ---
  1006. -- Introspection logic. This module implements Lua objects introspection and
  1007. -- generates a [DBGP](http://xdebug.org/docs-dbgp.php) compatible
  1008. -- [LOM](http://matthewwild.co.uk/projects/luaexpat/lom.html) data scructure.
  1009. -- @module debugger.introspection
  1010. local M = { }
  1011. ---
  1012. -- Represent the actual data to send to the debugger.
  1013. -- Full XML specification can be found in [DBGP specification](http://xdebug.org/docs-dbgp.php#properties-variables-and-values).
  1014. -- Modifying properties after their generation is possible (as actual data serialization/sending is delayed)
  1015. -- but should be used with care. The XML structure uses the [LOM](http://matthewwild.co.uk/projects/luaexpat/lom.html)
  1016. -- format, refer to these documents to get more informations about fields.
  1017. --
  1018. -- In addition to table fields, it has an array part, `[1]` being the string representation (base64 encoded),
  1019. -- possibly followed by chlid properties (@{#DBGPProperty} themselves)
  1020. --
  1021. -- @field #string tag Always "property"
  1022. -- @field #table attr XML attributes, see DBGP specification
  1023. -- @type DBGPProperty
  1024. ---
  1025. -- Inpectors table, contain all inspector functions.
  1026. -- Keys are either type names (`string`, `number`, ...) or metatables
  1027. -- that have a custom inspector attached.
  1028. -- @field [parent=#debugger.introspection] #table inspectors
  1029. M.inspectors = { }
  1030. ---
  1031. -- Generate a DBGP property if needed. If data is in data pagination and recursion depth ranges,
  1032. -- and send a property to the debugger, otherwise drop current property.
  1033. -- @param #string name Property name (displayed in IDE)
  1034. -- @param #string typename Type name (displayed in IDE)
  1035. -- @param #string repr Value string representation
  1036. -- @param #DBGPProperty parent Parent property
  1037. -- @param #string fullname Lua expression used to get value back in further calls
  1038. -- @return #table description
  1039. -- @function [parent=#debugger.introspection] property
  1040. M.property = coyield
  1041. ---
  1042. -- Adds a probe that will be called for every unknown table/userdata.
  1043. -- @param #function probe Inspector function to call.
  1044. -- @function [parent=#debugger.introspection] add_probe
  1045. M.add_probe = function(probe) probes[#probes + 1] = probe end
  1046. ---
  1047. -- Inspects a Lua value by dispatching it to correct inspector. Inspector functions have the same API.
  1048. -- @param #string name Property name (will be displayed by IDE)
  1049. -- @param value Value to inspect
  1050. -- @param #table parent Parent property (LOM table of the )
  1051. -- @param #string fullname Expression used to retrieve `value` for further debugger calls
  1052. -- @return #DBGPProperty The inspected value as returned by @{debugger.introspection#debugger.introspection.property}.
  1053. -- @return #nil If the value has not been inspected
  1054. -- @function [parent=#debugger.introspection] inspect
  1055. M.inspect = function(name, value, parent, fullname)
  1056. return (M.inspectors[type(value)] or M.inspectors.default)(name, value, parent, fullname)
  1057. end
  1058. -- ----------------- --
  1059. -- Utility functions --
  1060. -- ----------------- --
  1061. local function default_inspector(name, value, parent, fullname)
  1062. return M.property(name, type(value), tostring(value), parent, fullname)
  1063. end
  1064. -- Inspects types that can have a metatable (table and userdata). Returns
  1065. -- 1) generated property
  1066. -- 2) boolean indicating whether a custom inspector has been called (in that case, do not process value any further)
  1067. local function metatable_inspector(name, value, parent, fullname)
  1068. local mt = getmetatable(value)
  1069. do
  1070. -- find by metatable
  1071. local custom = M.inspectors[mt]
  1072. if custom then return custom(name, value, parent, fullname), true end
  1073. -- or else call probes
  1074. for i=1, #probes do
  1075. local prop = probes[i](name, value, parent, fullname)
  1076. if prop then return prop, true end
  1077. end
  1078. end
  1079. local prop = default_inspector(name, value, parent, fullname)
  1080. if mt and prop then
  1081. local mtprop = M.inspect("metatable", mt, prop, "metatable["..prop.attr.fullname.."]")
  1082. if mtprop then mtprop.attr.type = "special" end
  1083. end
  1084. return prop, false
  1085. end
  1086. local function fancy_func_repr(f, info)
  1087. local args = {}
  1088. for i=1, info.nparams do
  1089. args[i] = debug.getlocal(f, i)
  1090. end
  1091. if info.isvararg then
  1092. args[#args+1] = "..."
  1093. end
  1094. return "function(" .. tconcat(args, ", ") .. ")"
  1095. end
  1096. --- Generate a name siutable for table index syntax
  1097. -- @param name Key name
  1098. -- @return #string A table index style index
  1099. -- @usage generate_printable_key('foo') => '["foo"]'
  1100. -- @usage generate_printable_key(12) => '[12]'
  1101. -- @usage generate_printable_key({}) => '[table: 0x12345678]
  1102. -- @function [parent=#debugger.introspection] generate_printable_key
  1103. local function generate_printable_key(name)
  1104. return "[" .. (type(name) == "string" and sformat("%q", name) or tostring(name)) .. "]"
  1105. end
  1106. M.generate_printable_key = generate_printable_key
  1107. -- Used to store complex keys (other than string and number) as they cannot be passed in text
  1108. -- For these keys, the resulting expression will not be the key itself but "key_cache[...]"
  1109. -- where key_cache must be mapped to this table to resolve key correctly.
  1110. M.key_cache = setmetatable({ n=0 }, { __mode = "v" })
  1111. local function generate_key(name)
  1112. local tname = type(name)
  1113. if tname == "string" then return sformat("%q", name)
  1114. elseif tname == "number" or tname == "boolean" then return tostring(name)
  1115. else -- complex key, use key_cache for lookup
  1116. local i = M.key_cache.n
  1117. M.key_cache[i] = name
  1118. M.key_cache.n = i+1
  1119. return "key_cache["..tostring(i).."]"
  1120. end
  1121. end
  1122. --- Generate a usable fullname for a value.
  1123. -- Based on parent fullname and key value, return a valid Lua expression.
  1124. -- Key can be any value (as anything can act as table key). If it cannot
  1125. -- be serialized (only string, number and boolean can), it will be temporarly
  1126. -- stored in an internal cache to be retrieved later.
  1127. -- @param #string parent Parent fullname
  1128. -- @param key The child key to generate fullname for
  1129. -- @return #string A valid fullname expression
  1130. -- @function [parent=#debugger.introspection] make_fullname
  1131. local function make_fullname(parent, key)
  1132. return parent .. "[" .. generate_key(key) .. "]"
  1133. end
  1134. M.make_fullname = make_fullname
  1135. -- ---------- --
  1136. -- Inspectors --
  1137. -- ---------- --
  1138. M.inspectors.number = default_inspector
  1139. M.inspectors.boolean = default_inspector
  1140. M.inspectors["nil"] = default_inspector
  1141. M.inspectors.userdata = default_inspector
  1142. M.inspectors.thread = default_inspector
  1143. M.inspectors.default = default_inspector -- allows 3rd party inspectors to use the default inspector if needed
  1144. M.inspectors.userdata = function(name, value, parent, fullname)
  1145. return (metatable_inspector(name, value, parent, fullname)) -- drop second return value
  1146. end
  1147. M.inspectors.string = function(name, value, parent, fullname)
  1148. -- escape linebreaks as \n and not as \<0x0A> like %q does
  1149. return M.property(name, "string", sformat("%q", value):gsub("\\\n", "\\n"), parent, fullname)
  1150. end
  1151. M.inspectors["function"] = function(name, value, parent, fullname)
  1152. local info = debug.getinfo(value, "nSflu")
  1153. local prop
  1154. if info.what ~= "C" then
  1155. -- try to create a fancy representation if possible
  1156. local repr = info.nparams and fancy_func_repr(value, info) or tostring(value)
  1157. if info.source:sub(1,1) == "@" then
  1158. repr = repr .. "\n" .. platform.get_uri("@" .. info.source) .. "\n" .. tostring(info.linedefined)
  1159. end
  1160. prop = M.property(name, "function (Lua)", repr, parent, fullname)
  1161. else
  1162. prop = M.property(name, "function", tostring(value), parent, fullname)
  1163. end
  1164. if not prop then return nil end
  1165. -- (5.1 only) environment is dumped only if it is different from global environment
  1166. -- TODO: this is not a correct behavior: environment should be dumped if is different from current stack level one
  1167. local fenv = getfenv and getfenv(value)
  1168. if fenv and fenv ~= getfenv(0) then
  1169. local fenvprop = M.inspect("environment", fenv, prop, "environment["..prop.attr.fullname.."]")
  1170. if fenvprop then fenvprop.attr.type = "special" end
  1171. end
  1172. return prop
  1173. end
  1174. M.inspectors.table = function(name, value, parent, fullname)
  1175. local prop, iscustom = metatable_inspector(name, value, parent, fullname)
  1176. if not prop or iscustom then return prop end
  1177. -- iterate over table values and detect arrays at the same time
  1178. -- next is used to circumvent __pairs metamethod in 5.2
  1179. local isarray, i = true, 1
  1180. for k,v in next, value, nil do
  1181. M.inspect(generate_printable_key(k), v, prop, make_fullname(fullname, k))
  1182. -- array detection: keys should be accessible by 1..n keys
  1183. isarray = isarray and rawget(value, i) ~= nil
  1184. i = i + 1
  1185. end
  1186. -- empty tables are considered as tables
  1187. if isarray and i > 1 then prop.attr.type = "sequence" end
  1188. return prop
  1189. end
  1190. M.inspectors[MULTIVAL_MT] = function(name, value, parent, fullname)
  1191. if value.n == 1 then
  1192. -- return directly the value as result
  1193. return M.inspect(name, value[1], parent, fullname)
  1194. else
  1195. -- wrap values inside a multival container
  1196. local prop = M.property(name, "multival", "", parent, fullname)
  1197. if not prop then return nil end
  1198. for i=1, value.n do
  1199. M.inspect(generate_printable_key(i), value[i], prop, fullname .. "[" .. i .. "]")
  1200. end
  1201. return prop
  1202. end
  1203. end
  1204. -- ------------ --
  1205. -- Internal API --
  1206. -- ------------ --
  1207. -- Used to inspect "multival" or "vararg" values. The typical use is to pack function result(s) in a single
  1208. -- value to inspect. The Multival instances can be passed to make_property as a single value, they will be
  1209. -- correctly reported to debugger
  1210. function M.Multival(...)
  1211. return setmetatable({ n=select("#", ...), ... }, MULTIVAL_MT)
  1212. end
  1213. --- Makes a property form a name/value pair (and fullname). This is an **internal** function, and should not be used by 3rd party inspectors.
  1214. -- @param #number cxt_id Context ID in which this value resides (workaround bug 352316)
  1215. -- @param value The value to debug
  1216. -- @param name The name associated with value, passed through tostring, so it can be anything
  1217. -- @param #string fullname A Lua expression to eval to get that property again (if nil, computed automatically)
  1218. -- @param #number depth The maximum property depth (recursive calls)
  1219. -- @param #number pagesize maximum children to include
  1220. -- @param #number page The page to generate (0 based)
  1221. -- @param #number size_limit Optional, if set, the maximum size of the string representation (in bytes)
  1222. -- @param #boolean safe_name If true, does not encode the name as table key
  1223. -- @return #DBGPProperty root property
  1224. -- @function [parent=#debugger.introspection] make_property
  1225. --TODO BUG ECLIPSE TOOLSLINUX-99 352316 : as a workaround, context is encoded into the fullname property
  1226. M.make_property = function(cxt_id, value, name, fullname, depth, pagesize, page, size_limit, safe_name)
  1227. fullname = fullname or "(...)[" .. generate_key(name) .. "]"
  1228. if not safe_name then name = generate_printable_key(name) end
  1229. local generator = cocreate(function() return M.inspect(name, value, nil, fullname) end)
  1230. local propstack = { }
  1231. local rootnode
  1232. local catchthis = true
  1233. local nodestoskip = page * pagesize -- nodes to skip at root level to respect pagination
  1234. local fullname_prefix = tostring(cxt_id).."|"
  1235. while true do
  1236. local succes, name, datatype, repr, parent, fullname = assert(coresume(generator, catchthis and propstack[#propstack] or nil))
  1237. -- finalize and pop all finished properties
  1238. while propstack[#propstack] ~= parent do
  1239. local topop = propstack[#propstack]
  1240. topop.attr.fullname = util.rawb64(fullname_prefix .. topop.attr.fullname)
  1241. propstack[#propstack] = nil
  1242. end
  1243. if costatus(generator) == "dead" then break end
  1244. local prop = {
  1245. tag = "property",
  1246. attr = {
  1247. children = 0,
  1248. pagesize = pagesize,
  1249. page = parent and 0 or page,
  1250. type = datatype,
  1251. name = name,
  1252. fullname = fullname,
  1253. encoding = "base64",
  1254. size = #repr,
  1255. },
  1256. util.b64(size_limit and repr:sub(1, size_limit) or repr)
  1257. }
  1258. if parent then
  1259. parent.attr.children = 1
  1260. parent.attr.numchildren = (parent.attr.numchildren or 0) + 1
  1261. -- take pagination into accont to know if node needs to be catched
  1262. catchthis = #parent <= pagesize and #propstack <= depth
  1263. if parent == rootnode then
  1264. catchthis = catchthis and nodestoskip <= 0
  1265. nodestoskip = nodestoskip - 1
  1266. end
  1267. -- add node to tree
  1268. if catchthis then
  1269. parent[#parent + 1] = prop
  1270. propstack[#propstack + 1] = prop
  1271. end
  1272. else
  1273. rootnode = prop
  1274. catchthis = true
  1275. propstack[#propstack + 1] = prop
  1276. end
  1277. end
  1278. return rootnode
  1279. end
  1280. return M
  1281. end
  1282. --------------------------------------------------------------------------------
  1283. -- End of moduledebugger.introspection
  1284. --------------------------------------------------------------------------------
  1285. --------------------------------------------------------------------------------
  1286. -- Module debugger.plugins.ffi
  1287. package.preload["debugger.plugins.ffi"] = function(...)
  1288. -------------------------------------------------------------------------------
  1289. -- Copyright (c) 2012-2013 Julien Desgats
  1290. -- All rights reserved. This program and the accompanying materials
  1291. -- are made available under the terms of the Eclipse Public License v1.0
  1292. -- which accompanies this distribution, and is available at
  1293. -- http://www.eclipse.org/legal/epl-v10.html
  1294. --
  1295. -- Contributors:
  1296. -- Julien Desgats - initial API and implementation
  1297. -------------------------------------------------------------------------------
  1298. -- LuaJIT cdata introspection library.
  1299. -------------------------------------------------------------------------------
  1300. -- known issues:
  1301. -- * references are de-referenced event if inspect_references is unset
  1302. -- * is automatic pointer and reference de-referencing is possible ?
  1303. -- (only for first item in case of arrays). Possible leads:
  1304. -- http://stackoverflow.com/questions/7134590/how-to-test-if-an-address-is-readable-in-linux-userspace-app
  1305. -- http://www.softwareverify.com/blog/?p=319
  1306. -- * when setting a value from Eclipse, the type is sometimes changed (e.g. int => number)
  1307. local introspection = require "debugger.introspection"
  1308. local reflect = require "debugger.plugins.ffi.reflect"
  1309. local ffi = require "ffi"
  1310. local tostring, tonumber, type, assert, sformat, tconcat = tostring, tonumber, type, assert, string.format, table.concat
  1311. local M = { }
  1312. --- Whether the reference types are inspected. Usually references should be safe (at least a bit
  1313. -- safer than pointers) so they are inspected. If a reference points to unsafe memory, the whole
  1314. -- program could crash !
  1315. -- If this feature is disabled, deeply nested C types will not be displayed correctly as evaluation
  1316. -- has a recursion limit, any further evaluation is done through references.
  1317. M.inspect_references = true
  1318. local function make_typename(refct)
  1319. local t = refct.what
  1320. if t == "int" then
  1321. if refct.bool then t = "bool"
  1322. else
  1323. -- use C99 type notation to give more details about acutal type
  1324. t = (refct.unsigned and "uint" or "int") .. tostring(refct.size * 8) .. "_t"
  1325. end
  1326. elseif t == "float" then
  1327. -- assume IEEE754
  1328. if refct.size == 8 then t = "double"
  1329. elseif refct.size == 16 then t = "long double" -- not really sure this one is always true
  1330. end
  1331. elseif t == "struct" or t == "enum" or t == "union" then
  1332. t = refct.name and (t .. " " .. refct.name) or ("anonymous "..t)
  1333. elseif t == "func" then
  1334. t = "function (FFI)"
  1335. elseif t == "ptr" then
  1336. t = make_typename(refct.element_type) .. "*"
  1337. elseif t == "ref" then
  1338. t = make_typename(refct.element_type) .. "&"
  1339. elseif t == "field" then
  1340. return make_typename(refct.type)
  1341. elseif t == "bitfield" then
  1342. t = (refct.type.unsigned and "unsigned" or "signed") .. ":" .. tostring(refct.size * 8)
  1343. refct = refct.type
  1344. end
  1345. if refct.const then t = "const " .. t end
  1346. if refct.volatile then t = "volatile " .. t end
  1347. return t
  1348. end
  1349. -- if cdatakind is unknown, this one will be called
  1350. local default_inspector = introspection.inspectors.number
  1351. local inspect
  1352. -- recursion must be handled with some care: if we call regular introspection.inspect
  1353. -- we may create boxed references or Lua native objects which will be inspected as such
  1354. -- (leading to wrong type names).
  1355. local function recurse(name, value, parent, fullname, refct)
  1356. if type(value) == "cdata" then
  1357. return inspect(name, value, parent, fullname, refct)
  1358. else
  1359. local prop = introspection.inspect(name, value, parent, fullname)
  1360. if prop then
  1361. prop.attr.type = make_typename(refct)
  1362. end
  1363. return prop
  1364. end
  1365. end
  1366. -- cdata specific inspectors
  1367. local inspectors = {
  1368. struct = function(name, value, parent, fullname, refct)
  1369. local prop = introspection.property(name, make_typename(refct), tostring(value), parent, fullname)
  1370. -- inspect children, if needed
  1371. if prop then
  1372. for member in refct:members() do
  1373. local mname = member.name
  1374. recurse(mname, value[mname], prop, fullname .. sformat('[%q]', mname), member)
  1375. end
  1376. end
  1377. return prop
  1378. end,
  1379. array = function(name, value, parent, fullname, refct)
  1380. local etype = refct.element_type
  1381. -- for VLAs, reflect does not give size
  1382. local size = refct.size ~= "none" and refct.size or ffi.sizeof(value)
  1383. size = size and (size / etype.size) -- we've got the byte size, not element count
  1384. local typename = make_typename(etype)
  1385. local prop = introspection.property(name, typename .. "[" .. (tostring(size) or "") .. "]", tostring(value), parent, fullname)
  1386. if prop and size then
  1387. for i=0, size-1 do
  1388. local idx = "["..tostring(i).."]"
  1389. recurse(idx, value[i], prop, fullname .. idx, etype)
  1390. end
  1391. end
  1392. return prop
  1393. end,
  1394. func = function(name, value, parent, fullname, refct)
  1395. local args = { }
  1396. for arg in refct:arguments() do
  1397. args[#args + 1] = make_typename(arg.type) .. " " .. arg.name
  1398. end
  1399. if refct.vararg then
  1400. args[#args + 1] = "..."
  1401. end
  1402. local repr = make_typename(refct.return_type) .. " " .. refct.name .. "(" .. tconcat(args, ", ") .. ")"
  1403. return introspection.property(name, make_typename(refct), repr, parent, fullname)
  1404. end,
  1405. enum = function(name, value, parent, fullname, refct)
  1406. local repr = tonumber(value)
  1407. -- try to convert numeric value into enum name
  1408. --TODO: is there a faster method to make it ?
  1409. for val in refct:values() do
  1410. if val.value == repr then
  1411. repr = val.name
  1412. break
  1413. end
  1414. end
  1415. return introspection.property(name, make_typename(refct), tostring(repr), parent, fullname)
  1416. end,
  1417. ref = function(name, value, parent, fullname, refct)
  1418. -- this may be unsafe, see inspect_references setting
  1419. local typename = make_typename(refct)
  1420. if not M.inspect_references then
  1421. return introspection.property(name, typename, tostring(value), parent, fullname)
  1422. end
  1423. local prop = recurse(name, value, parent, fullname, refct.element_type)
  1424. if prop then
  1425. prop.attr.type = typename
  1426. end
  1427. return prop
  1428. end,
  1429. int = function(name, value, parent, fullname, refct)
  1430. return introspection.property(name, make_typename(refct), tostring(tonumber(value)), parent, fullname)
  1431. end,
  1432. -- pointers are too unsafe, do not inspect them
  1433. ptr = function(name, value, parent, fullname, refct)
  1434. return introspection.property(name, make_typename(refct), tostring(value), parent, fullname)
  1435. end,
  1436. }
  1437. inspectors.union = inspectors.struct
  1438. inspectors.float = inspectors.int
  1439. -- for struct/union fields, the actual type is nested into the refct
  1440. inspectors.field = function(name, value, parent, fullname, refct)
  1441. return inspect(name, value, parent, fullname, refct.type)
  1442. end
  1443. inspectors.bitfield = inspectors.field
  1444. inspect = function(name, value, parent, fullname, refct)
  1445. -- inspect only values, not ctypes
  1446. --FIXME: this cause references to be dereferenced and crash the process if they are wrong !
  1447. if ffi.typeof(value) ~= value then
  1448. refct = refct or reflect.typeof(value)
  1449. return (inspectors[refct.what] or default_inspector)(name, value, parent, fullname, refct)
  1450. end
  1451. -- return a simple property for ctypes
  1452. return introspection.property(name, "ctype", tostring(value), parent, fullname)
  1453. end
  1454. introspection.inspectors.cdata = inspect
  1455. return M
  1456. end
  1457. --------------------------------------------------------------------------------
  1458. -- End of moduledebugger.plugins.ffi
  1459. --------------------------------------------------------------------------------
  1460. --------------------------------------------------------------------------------
  1461. -- Module debugger.plugins.ffi.reflect
  1462. package.preload["debugger.plugins.ffi.reflect"] = function(...)
  1463. --[[ LuaJIT FFI reflection Library ]]--
  1464. --[[ Copyright (C) 2013 Peter Cawley <lua@corsix.org>. All rights reserved.
  1465. Permission is hereby granted, free of charge, to any person obtaining a copy
  1466. of this software and associated documentation files (the "Software"), to deal
  1467. in the Software without restriction, including without limitation the rights
  1468. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  1469. copies of the Software, and to permit persons to whom the Software is
  1470. furnished to do so, subject to the following conditions:
  1471. The above copyright notice and this permission notice shall be included in
  1472. all copies or substantial portions of the Software.
  1473. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1474. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1475. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1476. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  1477. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  1478. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  1479. THE SOFTWARE.
  1480. --]]
  1481. local ffi = require "ffi"
  1482. local bit = require "bit"
  1483. local reflect = {}
  1484. -- Relevant minimal definitions from lj_ctype.h
  1485. ffi.cdef [[
  1486. typedef struct CType {
  1487. uint32_t info;
  1488. uint32_t size;
  1489. uint16_t sib;
  1490. uint16_t next;
  1491. uint32_t name;
  1492. } CType;
  1493. typedef struct CTState {
  1494. CType *tab;
  1495. uint32_t top;
  1496. uint32_t sizetab;
  1497. void *L;
  1498. void *g;
  1499. void *finalizer;
  1500. void *miscmap;
  1501. } CTState;
  1502. ]]
  1503. local function gc_str(gcref) -- Convert a GCref (to a GCstr) into a string
  1504. if gcref ~= 0 then
  1505. local ts = ffi.cast("uint32_t*", gcref)
  1506. return ffi.string(ts + 4, ts[3])
  1507. end
  1508. end
  1509. local function memptr(gcobj)
  1510. return tonumber(tostring(gcobj):match"%x*$", 16)
  1511. end
  1512. -- Acquire a pointer to this Lua universe's CTState
  1513. local CTState do
  1514. local co = coroutine.create(function()end) -- Any live coroutine will do.
  1515. local uint32_ptr = ffi.typeof("uint32_t*")
  1516. local G = ffi.cast(uint32_ptr, ffi.cast(uint32_ptr, memptr(co))[2])
  1517. -- In global_State, `MRef ctype_state` is immediately before `GCRef gcroot[GCROOT_MAX]`.
  1518. -- We first find (an entry in) gcroot by looking for a metamethod name string.
  1519. local anchor = ffi.cast("uint32_t", ffi.cast("const char*", "__index"))
  1520. local i = 0
  1521. while math.abs(tonumber(G[i] - anchor)) > 64 do
  1522. i = i + 1
  1523. end
  1524. -- We then work backwards looking for something resembling ctype_state.
  1525. repeat
  1526. i = i - 1
  1527. CTState = ffi.cast("CTState*", G[i])
  1528. until ffi.cast(uint32_ptr, CTState.g) == G
  1529. end
  1530. -- Acquire the CTState's miscmap table as a Lua variable
  1531. local miscmap do
  1532. local t = {}; t[0] = t
  1533. local tvalue = ffi.cast("uint32_t*", memptr(t))[2]
  1534. ffi.cast("uint32_t*", tvalue)[ffi.abi"le" and 0 or 1] = ffi.cast("uint32_t", ffi.cast("uintptr_t", CTState.miscmap))
  1535. miscmap = t[0]
  1536. end
  1537. -- Information for unpacking a `struct CType`.
  1538. -- One table per CT_* constant, containing:
  1539. -- * A name for that CT_
  1540. -- * Roles of the cid and size fields.
  1541. -- * Whether the sib field is meaningful.
  1542. -- * Zero or more applicable boolean flags.
  1543. local CTs = {[0] =
  1544. {"int",
  1545. "", "size", false,
  1546. {0x08000000, "bool"},
  1547. {0x04000000, "float", "subwhat"},
  1548. {0x02000000, "const"},
  1549. {0x01000000, "volatile"},
  1550. {0x00800000, "unsigned"},
  1551. {0x00400000, "long"},
  1552. },
  1553. {"struct",
  1554. "", "size", true,
  1555. {0x02000000, "const"},
  1556. {0x01000000, "volatile"},
  1557. {0x00800000, "union", "subwhat"},
  1558. {0x00100000, "vla"},
  1559. },
  1560. {"ptr",
  1561. "element_type", "size", false,
  1562. {0x02000000, "const"},
  1563. {0x01000000, "volatile"},
  1564. {0x00800000, "ref", "subwhat"},
  1565. },
  1566. {"array",
  1567. "element_type", "size", false,
  1568. {0x08000000, "vector"},
  1569. {0x04000000, "complex"},
  1570. {0x02000000, "const"},
  1571. {0x01000000, "volatile"},
  1572. {0x00100000, "vla"},
  1573. },
  1574. {"void",
  1575. "", "size", false,
  1576. {0x02000000, "const"},
  1577. {0x01000000, "volatile"},
  1578. },
  1579. {"enum",
  1580. "type", "size", true,
  1581. },
  1582. {"func",
  1583. "return_type", "nargs", true,
  1584. {0x00800000, "vararg"},
  1585. {0x00400000, "sse_reg_params"},
  1586. },
  1587. {"typedef", -- Not seen
  1588. "element_type", "", false,
  1589. },
  1590. {"attrib", -- Only seen internally
  1591. "type", "value", true,
  1592. },
  1593. {"field",
  1594. "type", "offset", true,
  1595. },
  1596. {"bitfield",
  1597. "", "offset", true,
  1598. {0x08000000, "bool"},
  1599. {0x02000000, "const"},
  1600. {0x01000000, "volatile"},
  1601. {0x00800000, "unsigned"},
  1602. },
  1603. {"constant",
  1604. "type", "value", true,
  1605. {0x02000000, "const"},
  1606. },
  1607. {"extern", -- Not seen
  1608. "CID", "", true,
  1609. },
  1610. {"kw", -- Not seen
  1611. "TOK", "size",
  1612. },
  1613. }
  1614. -- Set of CType::cid roles which are a CTypeID.
  1615. local type_keys = {
  1616. element_type = true,
  1617. return_type = true,
  1618. value_type = true,
  1619. type = true,
  1620. }
  1621. -- Create a metatable for each CT.
  1622. local metatables = {
  1623. }
  1624. for _, CT in ipairs(CTs) do
  1625. local what = CT[1]
  1626. local mt = {__index = {}}
  1627. metatables[what] = mt
  1628. end
  1629. -- Logic for merging an attribute CType onto the annotated CType.
  1630. local CTAs = {[0] =
  1631. function(a, refct) error("TODO: CTA_NONE") end,
  1632. function(a, refct) error("TODO: CTA_QUAL") end,
  1633. function(a, refct)
  1634. a = 2^a.value
  1635. refct.alignment = a
  1636. refct.attributes.align = a
  1637. end,
  1638. function(a, refct)
  1639. refct.transparent = true
  1640. refct.attributes.subtype = refct.typeid
  1641. end,
  1642. function(a, refct) refct.sym_name = a.name end,
  1643. function(a, refct) error("TODO: CTA_BAD") end,
  1644. }
  1645. -- C function calling conventions (CTCC_* constants in lj_refct.h)
  1646. local CTCCs = {[0] =
  1647. "cdecl",
  1648. "thiscall",
  1649. "fastcall",
  1650. "stdcall",
  1651. }
  1652. local function refct_from_id(id) -- refct = refct_from_id(CTypeID)
  1653. local ctype = CTState.tab[id]
  1654. local CT_code = bit.rshift(ctype.info, 28)
  1655. local CT = CTs[CT_code]
  1656. local what = CT[1]
  1657. local refct = setmetatable({
  1658. what = what,
  1659. typeid = id,
  1660. name = gc_str(ctype.name),
  1661. }, metatables[what])
  1662. -- Interpret (most of) the CType::info field
  1663. for i = 5, #CT do
  1664. if bit.band(ctype.info, CT[i][1]) ~= 0 then
  1665. if CT[i][3] == "subwhat" then
  1666. refct.what = CT[i][2]
  1667. else
  1668. refct[CT[i][2]] = true
  1669. end
  1670. end
  1671. end
  1672. if CT_code <= 5 then
  1673. refct.alignment = bit.lshift(1, bit.band(bit.rshift(ctype.info, 16), 15))
  1674. elseif what == "func" then
  1675. refct.convention = CTCCs[bit.band(bit.rshift(ctype.info, 16), 3)]
  1676. end
  1677. if CT[2] ~= "" then -- Interpret the CType::cid field
  1678. local k = CT[2]
  1679. local cid = bit.band(ctype.info, 0xffff)
  1680. if type_keys[k] then
  1681. if cid == 0 then
  1682. cid = nil
  1683. else
  1684. cid = refct_from_id(cid)
  1685. end
  1686. end
  1687. refct[k] = cid
  1688. end
  1689. if CT[3] ~= "" then -- Interpret the CType::size field
  1690. local k = CT[3]
  1691. refct[k] = ctype.size
  1692. if k == "size" and bit.bnot(refct[k]) == 0 then
  1693. refct[k] = "none"
  1694. end
  1695. end
  1696. if what == "attrib" then
  1697. -- Merge leading attributes onto the type being decorated.
  1698. local CTA = CTAs[bit.band(bit.rshift(ctype.info, 16), 0xff)]
  1699. if refct.type then
  1700. local ct = refct.type
  1701. ct.attributes = {}
  1702. CTA(refct, ct)
  1703. ct.typeid = refct.typeid
  1704. refct = ct
  1705. else
  1706. refct.CTA = CTA
  1707. end
  1708. elseif what == "bitfield" then
  1709. -- Decode extra bitfield fields, and make it look like a normal field.
  1710. refct.offset = refct.offset + bit.band(ctype.info, 127) / 8
  1711. refct.size = bit.band(bit.rshift(ctype.info, 8), 127) / 8
  1712. refct.type = {
  1713. what = "int",
  1714. bool = refct.bool,
  1715. const = refct.const,
  1716. volatile = refct.volatile,
  1717. unsigned = refct.unsigned,
  1718. size = bit.band(bit.rshift(ctype.info, 16), 127),
  1719. }
  1720. refct.bool, refct.const, refct.volatile, refct.unsigned = nil
  1721. end
  1722. if CT[4] then -- Merge sibling attributes onto this type.
  1723. while ctype.sib ~= 0 do
  1724. local entry = CTState.tab[ctype.sib]
  1725. if CTs[bit.rshift(entry.info, 28)][1] ~= "attrib" then break end
  1726. if bit.band(entry.info, 0xffff) ~= 0 then break end
  1727. local sib = refct_from_id(ctype.sib)
  1728. sib:CTA(refct)
  1729. ctype = entry
  1730. end
  1731. end
  1732. return refct
  1733. end
  1734. local function sib_iter(s, refct)
  1735. repeat
  1736. local ctype = CTState.tab[refct.typeid]
  1737. if ctype.sib == 0 then return end
  1738. refct = refct_from_id(ctype.sib)
  1739. until refct.what ~= "attrib" -- Pure attribs are skipped.
  1740. return refct
  1741. end
  1742. local function siblings(refct)
  1743. -- Follow to the end of the attrib chain, if any.
  1744. while refct.attributes do
  1745. refct = refct_from_id(refct.attributes.subtype or CTState.tab[refct.typeid].sib)
  1746. end
  1747. return sib_iter, nil, refct
  1748. end
  1749. metatables.struct.__index.members = siblings
  1750. metatables.func.__index.arguments = siblings
  1751. metatables.enum.__index.values = siblings
  1752. local function find_sibling(refct, name)
  1753. local num = tonumber(name)
  1754. if num then
  1755. for sib in siblings(refct) do
  1756. if num == 1 then
  1757. return sib
  1758. end
  1759. num = num - 1
  1760. end
  1761. else
  1762. for sib in siblings(refct) do
  1763. if sib.name == name then
  1764. return sib
  1765. end
  1766. end
  1767. end
  1768. end
  1769. metatables.struct.__index.member = find_sibling
  1770. metatables.func.__index.argument = find_sibling
  1771. metatables.enum.__index.value = find_sibling
  1772. function reflect.typeof(x) -- refct = reflect.typeof(ct)
  1773. return refct_from_id(tonumber(ffi.typeof(x)))
  1774. end
  1775. function reflect.getmetatable(x) -- mt = reflect.getmetatable(ct)
  1776. return miscmap[-tonumber(ffi.typeof(x))]
  1777. end
  1778. return reflect
  1779. end
  1780. --------------------------------------------------------------------------------
  1781. -- End of moduledebugger.plugins.ffi.reflect
  1782. --------------------------------------------------------------------------------
  1783. --------------------------------------------------------------------------------
  1784. -- Module debugger.platform
  1785. package.preload["debugger.platform"] = function(...)
  1786. -------------------------------------------------------------------------------
  1787. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  1788. -- All rights reserved. This program and the accompanying materials
  1789. -- are made available under the terms of the Eclipse Public License v1.0
  1790. -- which accompanies this distribution, and is available at
  1791. -- http://www.eclipse.org/legal/epl-v10.html
  1792. --
  1793. -- Contributors:
  1794. -- Sierra Wireless - initial API and implementation
  1795. -------------------------------------------------------------------------------
  1796. -- Platform/OS specific features and path handling.
  1797. -------------------------------------------------------------------------------
  1798. local url = require "debugger.url"
  1799. local util = require "debugger.util"
  1800. local M = { }
  1801. -- Execution plaform (could be win or unix)
  1802. -- Used to manage file path difference between the 2 platform
  1803. local platform = nil
  1804. -- keep all computed URIs in cache (as they are quite long to compute)
  1805. local uri_cache = { }
  1806. -- parse a normalized path and return a table of each segment
  1807. -- you could precise the path seperator.
  1808. local function split(path,sep)
  1809. local t = {}
  1810. for w in path:gmatch("[^"..(sep or "/").."]+")do
  1811. table.insert(t, w)
  1812. end
  1813. return t
  1814. end
  1815. --- Returns a RFC2396 compliant URI for given source, or false if the mapping failed
  1816. local function get_abs_file_uri (source)
  1817. local uri
  1818. if source:sub(1,1) == "@" then -- real source file
  1819. local sourcepath = source:sub(2)
  1820. local normalizedpath = M.normalize(sourcepath)
  1821. if not M.is_path_absolute(normalizedpath) then
  1822. normalizedpath = M.normalize(M.base_dir .. "/" .. normalizedpath)
  1823. end
  1824. return M.to_file_uri(normalizedpath)
  1825. else -- dynamic code, stripped bytecode, tail return, ...
  1826. return false
  1827. end
  1828. end
  1829. --FIXME: as result is cached, changes in package.path that modify the module name are missed
  1830. -- (mostly affect main module when Lua interpreter is launched with an absolute path)
  1831. local function get_module_uri (source)
  1832. if source:sub(1,1) == "@" then -- real source file
  1833. local uri
  1834. local sourcepath = source:sub(2)
  1835. local normalizedpath = M.normalize(sourcepath)
  1836. local luapathtable = split (package.path, ";")
  1837. local is_source_absolute = M.is_path_absolute(sourcepath)
  1838. -- workarround : Add always the ?.lua entry to support
  1839. -- the case where file was loaded by : "lua myfile.lua"
  1840. table.insert(luapathtable,"?.lua")
  1841. for i,var in ipairs(luapathtable) do
  1842. -- avoid relative patterns matching absolute ones (e.g. ?.lua matches anything)
  1843. if M.is_path_absolute(var) == is_source_absolute then
  1844. local escaped = string.gsub(M.normalize(var),"[%^%$%(%)%%%.%[%]%*%+%-%?]",function(c) return "%"..c end)
  1845. local pattern = string.gsub(escaped,"%%%?","(.+)")
  1846. local modulename = string.match(normalizedpath,pattern)
  1847. if modulename then
  1848. modulename = string.gsub(modulename,"/",".");
  1849. -- if we find more than 1 possible modulename return the shorter
  1850. if not uri or string.len(uri)>string.len(modulename) then
  1851. uri = modulename
  1852. end
  1853. end
  1854. end
  1855. end
  1856. if uri then return "module:///"..uri end
  1857. end
  1858. return false
  1859. end
  1860. function M.get_uri (source)
  1861. -- search in cache
  1862. local uri = uri_cache[source]
  1863. if uri ~= nil then return uri end
  1864. -- not found, create uri
  1865. if util.features.uri == "module" then
  1866. uri = get_module_uri(source)
  1867. if not uri then uri = get_abs_file_uri (source) end
  1868. else
  1869. uri = get_abs_file_uri (source)
  1870. end
  1871. uri_cache[source] = uri
  1872. return uri
  1873. end
  1874. -- get path file from uri
  1875. function M.get_path (uri)
  1876. local parsed_path = assert(url.parse(uri))
  1877. if parsed_path.scheme == "file" then
  1878. return M.to_path(parsed_path)
  1879. else
  1880. -- search in cache
  1881. -- we should surely calculate it instead of find in cache
  1882. for k,v in pairs(uri_cache)do
  1883. if v == uri then
  1884. assert(k:sub(1,1) == "@")
  1885. return k:sub(2)
  1886. end
  1887. end
  1888. end
  1889. end
  1890. function M.normalize(path)
  1891. local parts = { }
  1892. for w in path:gmatch("[^/]+") do
  1893. if w == ".." and #parts ~=0 then table.remove(parts)
  1894. elseif w ~= "." then table.insert(parts, w)
  1895. end
  1896. end
  1897. return (path:sub(1,1) == "/" and "/" or "") .. table.concat(parts, "/")
  1898. end
  1899. function M.init(executionplatform,workingdirectory)
  1900. --------------------------
  1901. -- define current platform
  1902. --------------------------
  1903. -- check parameter
  1904. if executionplatform and executionplatform ~= "unix" and executionplatform ~="win" then
  1905. error("Unable to initialize platform module : execution platform should be 'unix' or 'win'.")
  1906. end
  1907. -- use parameter as current platform
  1908. if executionplatform then
  1909. platform = executionplatform
  1910. else
  1911. --if not define try to guess it.
  1912. local function iswindows()
  1913. local p = io.popen("echo %os%")
  1914. if p then
  1915. local result =p:read("*l")
  1916. p:close()
  1917. return result == "Windows_NT"
  1918. end
  1919. return false
  1920. end
  1921. local status, iswin = pcall(iswindows)
  1922. if status and iswin then
  1923. platform = "win"
  1924. else
  1925. platform = "unix"
  1926. end
  1927. end
  1928. --------------------------
  1929. -- platform dependent function
  1930. --------------------------
  1931. if platform == "unix" then
  1932. -- The Path separator character
  1933. M.path_sep = "/"
  1934. -- TODO the way to get the absolute path can be wrong if the program loads new source files by relative path after a cd.
  1935. -- currently, the directory is registered on start, this allows program to load any source file and then change working dir,
  1936. -- which is the most common use case.
  1937. M.base_dir = workingdirectory or os.getenv("PWD")
  1938. -- convert parsed URL table to file path for the current OS (see url.parse from luasocket)
  1939. M.to_file_uri = function (path) return url.build{scheme="file",authority="", path=path} end
  1940. -- return true is the path is absolute
  1941. -- the path must be normalized
  1942. M.is_path_absolute = function (path) return path:sub(1,1) == "/" end
  1943. -- convert absolute normalized path file to uri
  1944. M.to_path = function (parsed_url) return url.unescape(parsed_url.path) end
  1945. else
  1946. -- Implementations for Windows, see UNIX versions for documentation.
  1947. M.path_sep = "\\"
  1948. M.is_path_absolute = function (path) return path:match("^%a:/") end
  1949. M.to_file_uri = function (path) return url.build{scheme="file",authority="", path="/"..path} end
  1950. M.to_path = function (parsed_url) return url.unescape(parsed_url.path):gsub("^/", "") end
  1951. local unixnormalize = M.normalize
  1952. M.normalize = function(path) return unixnormalize(path:gsub("\\","/"):lower()) end
  1953. -- determine base dir
  1954. local function getworkingdirectory()
  1955. local p = io.popen("echo %cd%")
  1956. if p then
  1957. local res = p:read("*l")
  1958. p:close()
  1959. return M.normalize(res)
  1960. end
  1961. end
  1962. M.base_dir = workingdirectory or getworkingdirectory()
  1963. end
  1964. if not M.base_dir then error("Unable to determine the working directory.") end
  1965. end
  1966. return M
  1967. end
  1968. --------------------------------------------------------------------------------
  1969. -- End of moduledebugger.platform
  1970. --------------------------------------------------------------------------------
  1971. --------------------------------------------------------------------------------
  1972. -- Module debugger.util
  1973. package.preload["debugger.util"] = function(...)
  1974. -------------------------------------------------------------------------------
  1975. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  1976. -- All rights reserved. This program and the accompanying materials
  1977. -- are made available under the terms of the Eclipse Public License v1.0
  1978. -- which accompanies this distribution, and is available at
  1979. -- http://www.eclipse.org/legal/epl-v10.html
  1980. --
  1981. -- Contributors:
  1982. -- Sierra Wireless - initial API and implementation
  1983. -------------------------------------------------------------------------------
  1984. -- Utility functions.
  1985. -------------------------------------------------------------------------------
  1986. local M = { }
  1987. -- log system
  1988. local LEVELS = { ERROR = 0, WARNING = 1, INFO = 2, DETAIL = 3, DEBUG = 4 }
  1989. local LOG_LEVEL = LEVELS.WARNING
  1990. -- Debugger features handling. Any feature can be get like any regular table, setting features result in
  1991. -- error for unknown or read-only features.
  1992. M.features = setmetatable({ }, {
  1993. -- functions that format/validate data. If function is not provided, the feature cannot be modified.
  1994. validators = {
  1995. multiple_sessions = tonumber,
  1996. encoding = tostring,
  1997. max_children = tonumber,
  1998. max_data = tonumber,
  1999. max_depth = tonumber,
  2000. show_hidden = tonumber,
  2001. uri = tostring,
  2002. log_level = function(level_name)
  2003. -- set numerical index in internal var
  2004. LOG_LEVEL = assert(LEVELS[level_name], "No such level")
  2005. return level_name -- the displayed level is still the name
  2006. end,
  2007. },
  2008. __index = {
  2009. multiple_sessions = 0,
  2010. encoding ="UTF-8",
  2011. max_children = 32,
  2012. max_data = 0xFFFF,
  2013. max_depth = 1,
  2014. show_hidden = 1,
  2015. uri = "file",
  2016. log_level = "WARNING",
  2017. -- read only features
  2018. language_supports_threads = 0,
  2019. language_name = "Lua",
  2020. language_version = _VERSION,
  2021. protocol_version = 1,
  2022. supports_async = 1,
  2023. data_encoding = "base64",
  2024. breakpoint_languages = "Lua",
  2025. breakpoint_types = "line conditional",
  2026. },
  2027. __newindex = function(self, k, v)
  2028. local mt = getmetatable(self)
  2029. local values, validator = mt.__index, mt.validators[k]
  2030. if values[k] == nil then error("No such feature " .. tostring(k)) end
  2031. if not validator then error("The feature " .. tostring(k) .. " is read-only") end
  2032. v = assert(validator(v))
  2033. values[k] = v
  2034. end,
  2035. })
  2036. -- Wraps debug function and an attached thread
  2037. -- also handle stack & coroutine management differencies between Lua versions
  2038. local getinfo, getlocal, setlocal = debug.getinfo, debug.getlocal, debug.setlocal
  2039. -- Foreign thread is used to debug paused thread
  2040. local ForeignThreadMT = {
  2041. getinfo = function(self, level, what) return getinfo(self[1], level, what) end,
  2042. getlocal = function(self, level, idx) return getlocal(self[1], level, idx) end,
  2043. setlocal = function(self, level, idx, val) return setlocal(self[1], level, idx, val) end,
  2044. }
  2045. ForeignThreadMT.__index = ForeignThreadMT
  2046. function M.ForeignThread(coro) return setmetatable({ coro }, ForeignThreadMT) end
  2047. -- Current thread is used to debug the thread that caused the hook
  2048. -- intended to be used *ONLY* in debug loop (executed in a new thread)
  2049. local CurrentThreadMT = {
  2050. getinfo = function(self, level, what) return getinfo(self[1], level + 2, what) end,
  2051. getlocal = function(self, level, idx) return getlocal(self[1], level + 2, idx) end,
  2052. setlocal = function(self, level, idx, val) return setlocal(self[1], level + 2, idx, val) end,
  2053. }
  2054. CurrentThreadMT.__index = CurrentThreadMT
  2055. function M.CurrentThread(coro) return setmetatable({ coro }, CurrentThreadMT) end
  2056. -- Some version dependant functions
  2057. if _VERSION == "Lua 5.1" then
  2058. local loadstring, getfenv, setfenv, debug_getinfo, MainThread =
  2059. loadstring, getfenv, setfenv, debug.getinfo, nil
  2060. -- in 5.1 "t" flag does not exist and trigger an error so remove it from what
  2061. CurrentThreadMT.getinfo = function(self, level, what) return getinfo(self[1], level + 2, what:gsub("t", "", 1)) end
  2062. ForeignThreadMT.getinfo = function(self, level, what) return getinfo(self[1], level, what:gsub("t", "", 1)) end
  2063. -- when we're forced to start debug loop on top of program stack (when on main coroutine)
  2064. -- this requires some hackery to get right stack level
  2065. -- Fallback method to inspect running thread (only for main thread in 5.1 or for conditional breakpoints)
  2066. --- Gets a script stack level with additional debugger logic added
  2067. -- @param l (number) stack level to get for debugged script (0 based)
  2068. -- @return real Lua stack level suitable to be passed through deubg functions
  2069. local function get_script_level(l)
  2070. local hook = debug.gethook()
  2071. for i=2, math.huge do
  2072. if assert(debug.getinfo(i, "f")).func == hook then
  2073. return i + l -- the script to level is just below, but because of the extra call to this function, the level is ok for callee
  2074. end
  2075. end
  2076. end
  2077. if rawget(_G, "jit") then
  2078. MainThread = {
  2079. [1] = "main", -- as the raw thread object is used as table keys, provide a replacement.
  2080. -- LuaJIT completely eliminates tail calls from stack, so get_script_level retunrs wrong result in this case
  2081. getinfo = function(self, level, what) return getinfo(get_script_level(level) - 1, what:gsub("t", "", 1)) end,
  2082. getlocal = function(self, level, idx) return getlocal(get_script_level(level) - 1, idx) end,
  2083. setlocal = function(self, level, idx, val) return setlocal(get_script_level(level) - 1, idx, val) end,
  2084. }
  2085. else
  2086. MainThread = {
  2087. [1] = "main",
  2088. getinfo = function(self, level, what) return getinfo(get_script_level(level) , what:gsub("t", "", 1)) end,
  2089. getlocal = function(self, level, idx) return getlocal(get_script_level(level), idx) end,
  2090. setlocal = function(self, level, idx, val) return setlocal(get_script_level(level), idx, val) end,
  2091. }
  2092. end
  2093. -- If the VM is vanilla Lua 5.1 or LuaJIT 2 without 5.2 compatibility, there is no way to get a reference to
  2094. -- the main coroutine, so fall back to direct mode: the debugger loop is started on the top of main thread
  2095. -- and the actual level is recomputed each time
  2096. local oldCurrentThread = M.CurrentThread
  2097. M.CurrentThread = function(coro) return coro and oldCurrentThread(coro) or MainThread end
  2098. -- load a piece of code alog with its environment
  2099. function M.loadin(code, env)
  2100. local f,err = loadstring(code)
  2101. if not f then
  2102. return nil, err
  2103. else
  2104. return f and setfenv(f, env)
  2105. end
  2106. end
  2107. -- table that maps [gs]et environment to index
  2108. M.eval_env = setmetatable({ }, {
  2109. __index = function(self, func) return getfenv(func) end,
  2110. __newindex = function(self, func, env) return setfenv(func, env) end,
  2111. })
  2112. elseif _VERSION == "Lua 5.2" then
  2113. local load, debug_getinfo = load, debug.getinfo
  2114. function M.getinfo(coro, level, what)
  2115. if coro then return debug_getinfo(coro, level, what)
  2116. else return debug_getinfo(level + 1, what) end
  2117. end
  2118. function M.loadin(code, env) return load(code, nil, nil, env) end
  2119. -- no eval_env for 5.2 as functions does not have environments anymore
  2120. end
  2121. -- ----------------------------------------------------------------------------
  2122. -- Bare minimal log system.
  2123. -- ----------------------------------------------------------------------------
  2124. function M.log(level, msg, ...)
  2125. if (LEVELS[level] or -1) > LOG_LEVEL then return end
  2126. if select("#", ...) > 0 then msg = msg:format(...) end
  2127. io.base.stderr:write(string.format("DEBUGGER\t%s\t%s\n", level, msg))
  2128. end
  2129. return M
  2130. end
  2131. --------------------------------------------------------------------------------
  2132. -- End of moduledebugger.util
  2133. --------------------------------------------------------------------------------
  2134. --------------------------------------------------------------------------------
  2135. -- Module debugger.url
  2136. package.preload["debugger.url"] = function(...)
  2137. -----------------------------------------------------------------------------
  2138. -- URI parsing, composition and relative URL resolution
  2139. -- LuaSocket toolkit.
  2140. -- Author: Diego Nehab
  2141. -- RCS ID: $Id: url.lua,v 1.38 2006/04/03 04:45:42 diego Exp $
  2142. -----------------------------------------------------------------------------
  2143. -----------------------------------------------------------------------------
  2144. -- Declare module
  2145. -----------------------------------------------------------------------------
  2146. local string = require("string")
  2147. local base = _G
  2148. local table = require("table")
  2149. local _ENV = { }
  2150. if setfenv then setfenv(1, _ENV) end
  2151. -----------------------------------------------------------------------------
  2152. -- Module version
  2153. -----------------------------------------------------------------------------
  2154. _VERSION = "URL 1.0.1"
  2155. -----------------------------------------------------------------------------
  2156. -- Encodes a string into its escaped hexadecimal representation
  2157. -- Input
  2158. -- s: binary string to be encoded
  2159. -- Returns
  2160. -- escaped representation of string binary
  2161. -----------------------------------------------------------------------------
  2162. function escape(s)
  2163. return string.gsub(s, "([^A-Za-z0-9_])", function(c)
  2164. return string.format("%%%02x", string.byte(c))
  2165. end)
  2166. end
  2167. -----------------------------------------------------------------------------
  2168. -- Protects a path segment, to prevent it from interfering with the
  2169. -- url parsing.
  2170. -- Input
  2171. -- s: binary string to be encoded
  2172. -- Returns
  2173. -- escaped representation of string binary
  2174. -----------------------------------------------------------------------------
  2175. local function make_set(t)
  2176. local s = {}
  2177. for i,v in base.ipairs(t) do
  2178. s[t[i]] = 1
  2179. end
  2180. return s
  2181. end
  2182. -- these are allowed withing a path segment, along with alphanum
  2183. -- other characters must be escaped
  2184. local segment_set = make_set {
  2185. "-", "_", ".", "!", "~", "*", "'", "(",
  2186. ")", ":", "@", "&", "=", "+", "$", ",",
  2187. }
  2188. local function protect_segment(s)
  2189. return string.gsub(s, "([^A-Za-z0-9_])", function (c)
  2190. if segment_set[c] then return c
  2191. else return string.format("%%%02x", string.byte(c)) end
  2192. end)
  2193. end
  2194. -----------------------------------------------------------------------------
  2195. -- Encodes a string into its escaped hexadecimal representation
  2196. -- Input
  2197. -- s: binary string to be encoded
  2198. -- Returns
  2199. -- escaped representation of string binary
  2200. -----------------------------------------------------------------------------
  2201. function unescape(s)
  2202. return string.gsub(s, "%%(%x%x)", function(hex)
  2203. return string.char(base.tonumber(hex, 16))
  2204. end)
  2205. end
  2206. -----------------------------------------------------------------------------
  2207. -- Builds a path from a base path and a relative path
  2208. -- Input
  2209. -- base_path
  2210. -- relative_path
  2211. -- Returns
  2212. -- corresponding absolute path
  2213. -----------------------------------------------------------------------------
  2214. local function absolute_path(base_path, relative_path)
  2215. if string.sub(relative_path, 1, 1) == "/" then return relative_path end
  2216. local path = string.gsub(base_path, "[^/]*$", "")
  2217. path = path .. relative_path
  2218. path = string.gsub(path, "([^/]*%./)", function (s)
  2219. if s ~= "./" then return s else return "" end
  2220. end)
  2221. path = string.gsub(path, "/%.$", "/")
  2222. local reduced
  2223. while reduced ~= path do
  2224. reduced = path
  2225. path = string.gsub(reduced, "([^/]*/%.%./)", function (s)
  2226. if s ~= "../../" then return "" else return s end
  2227. end)
  2228. end
  2229. path = string.gsub(reduced, "([^/]*/%.%.)$", function (s)
  2230. if s ~= "../.." then return "" else return s end
  2231. end)
  2232. return path
  2233. end
  2234. -----------------------------------------------------------------------------
  2235. -- Parses a url and returns a table with all its parts according to RFC 2396
  2236. -- The following grammar describes the names given to the URL parts
  2237. -- <url> ::= <scheme>://<authority>/<path>;<params>?<query>#<fragment>
  2238. -- <authority> ::= <userinfo>@<host>:<port>
  2239. -- <userinfo> ::= <user>[:<password>]
  2240. -- <path> :: = {<segment>/}<segment>
  2241. -- Input
  2242. -- url: uniform resource locator of request
  2243. -- default: table with default values for each field
  2244. -- Returns
  2245. -- table with the following fields, where RFC naming conventions have
  2246. -- been preserved:
  2247. -- scheme, authority, userinfo, user, password, host, port,
  2248. -- path, params, query, fragment
  2249. -- Obs:
  2250. -- the leading '/' in {/<path>} is considered part of <path>
  2251. -----------------------------------------------------------------------------
  2252. function parse(url, default)
  2253. -- initialize default parameters
  2254. local parsed = {}
  2255. for i,v in base.pairs(default or parsed) do parsed[i] = v end
  2256. -- empty url is parsed to nil
  2257. if not url or url == "" then return nil, "invalid url" end
  2258. -- remove whitespace
  2259. -- url = string.gsub(url, "%s", "")
  2260. -- get fragment
  2261. url = string.gsub(url, "#(.*)$", function(f)
  2262. parsed.fragment = f
  2263. return ""
  2264. end)
  2265. -- get scheme
  2266. url = string.gsub(url, "^([%w][%w%+%-%.]*)%:",
  2267. function(s) parsed.scheme = s; return "" end)
  2268. -- get authority
  2269. url = string.gsub(url, "^//([^/]*)", function(n)
  2270. parsed.authority = n
  2271. return ""
  2272. end)
  2273. -- get query stringing
  2274. url = string.gsub(url, "%?(.*)", function(q)
  2275. parsed.query = q
  2276. return ""
  2277. end)
  2278. -- get params
  2279. url = string.gsub(url, "%;(.*)", function(p)
  2280. parsed.params = p
  2281. return ""
  2282. end)
  2283. -- path is whatever was left
  2284. if url ~= "" then parsed.path = url end
  2285. local authority = parsed.authority
  2286. if not authority then return parsed end
  2287. authority = string.gsub(authority,"^([^@]*)@",
  2288. function(u) parsed.userinfo = u; return "" end)
  2289. authority = string.gsub(authority, ":([^:]*)$",
  2290. function(p) parsed.port = p; return "" end)
  2291. if authority ~= "" then parsed.host = authority end
  2292. local userinfo = parsed.userinfo
  2293. if not userinfo then return parsed end
  2294. userinfo = string.gsub(userinfo, ":([^:]*)$",
  2295. function(p) parsed.password = p; return "" end)
  2296. parsed.user = userinfo
  2297. return parsed
  2298. end
  2299. -----------------------------------------------------------------------------
  2300. -- Rebuilds a parsed URL from its components.
  2301. -- Components are protected if any reserved or unallowed characters are found
  2302. -- Input
  2303. -- parsed: parsed URL, as returned by parse
  2304. -- Returns
  2305. -- a stringing with the corresponding URL
  2306. -----------------------------------------------------------------------------
  2307. function build(parsed)
  2308. local ppath = parse_path(parsed.path or "")
  2309. local url = build_path(ppath)
  2310. if parsed.params then url = url .. ";" .. parsed.params end
  2311. if parsed.query then url = url .. "?" .. parsed.query end
  2312. local authority = parsed.authority
  2313. if parsed.host then
  2314. authority = parsed.host
  2315. if parsed.port then authority = authority .. ":" .. parsed.port end
  2316. local userinfo = parsed.userinfo
  2317. if parsed.user then
  2318. userinfo = parsed.user
  2319. if parsed.password then
  2320. userinfo = userinfo .. ":" .. parsed.password
  2321. end
  2322. end
  2323. if userinfo then authority = userinfo .. "@" .. authority end
  2324. end
  2325. if authority then url = "//" .. authority .. url end
  2326. if parsed.scheme then url = parsed.scheme .. ":" .. url end
  2327. if parsed.fragment then url = url .. "#" .. parsed.fragment end
  2328. -- url = string.gsub(url, "%s", "")
  2329. return url
  2330. end
  2331. -----------------------------------------------------------------------------
  2332. -- Builds a absolute URL from a base and a relative URL according to RFC 2396
  2333. -- Input
  2334. -- base_url
  2335. -- relative_url
  2336. -- Returns
  2337. -- corresponding absolute url
  2338. -----------------------------------------------------------------------------
  2339. function absolute(base_url, relative_url)
  2340. if base.type(base_url) == "table" then
  2341. base_parsed = base_url
  2342. base_url = build(base_parsed)
  2343. else
  2344. base_parsed = parse(base_url)
  2345. end
  2346. local relative_parsed = parse(relative_url)
  2347. if not base_parsed then return relative_url
  2348. elseif not relative_parsed then return base_url
  2349. elseif relative_parsed.scheme then return relative_url
  2350. else
  2351. relative_parsed.scheme = base_parsed.scheme
  2352. if not relative_parsed.authority then
  2353. relative_parsed.authority = base_parsed.authority
  2354. if not relative_parsed.path then
  2355. relative_parsed.path = base_parsed.path
  2356. if not relative_parsed.params then
  2357. relative_parsed.params = base_parsed.params
  2358. if not relative_parsed.query then
  2359. relative_parsed.query = base_parsed.query
  2360. end
  2361. end
  2362. else
  2363. relative_parsed.path = absolute_path(base_parsed.path or "",
  2364. relative_parsed.path)
  2365. end
  2366. end
  2367. return build(relative_parsed)
  2368. end
  2369. end
  2370. -----------------------------------------------------------------------------
  2371. -- Breaks a path into its segments, unescaping the segments
  2372. -- Input
  2373. -- path
  2374. -- Returns
  2375. -- segment: a table with one entry per segment
  2376. -----------------------------------------------------------------------------
  2377. function parse_path(path)
  2378. local parsed = {}
  2379. path = path or ""
  2380. --path = string.gsub(path, "%s", "")
  2381. string.gsub(path, "([^/]+)", function (s) table.insert(parsed, s) end)
  2382. for i = 1, #parsed do
  2383. parsed[i] = unescape(parsed[i])
  2384. end
  2385. if string.sub(path, 1, 1) == "/" then parsed.is_absolute = 1 end
  2386. if string.sub(path, -1, -1) == "/" then parsed.is_directory = 1 end
  2387. return parsed
  2388. end
  2389. -----------------------------------------------------------------------------
  2390. -- Builds a path component from its segments, escaping protected characters.
  2391. -- Input
  2392. -- parsed: path segments
  2393. -- unsafe: if true, segments are not protected before path is built
  2394. -- Returns
  2395. -- path: corresponding path stringing
  2396. -----------------------------------------------------------------------------
  2397. function build_path(parsed, unsafe)
  2398. local path = ""
  2399. local n = #parsed
  2400. if unsafe then
  2401. for i = 1, n-1 do
  2402. path = path .. parsed[i]
  2403. path = path .. "/"
  2404. end
  2405. if n > 0 then
  2406. path = path .. parsed[n]
  2407. if parsed.is_directory then path = path .. "/" end
  2408. end
  2409. else
  2410. for i = 1, n-1 do
  2411. path = path .. protect_segment(parsed[i])
  2412. path = path .. "/"
  2413. end
  2414. if n > 0 then
  2415. path = path .. protect_segment(parsed[n])
  2416. if parsed.is_directory then path = path .. "/" end
  2417. end
  2418. end
  2419. if parsed.is_absolute then path = "/" .. path end
  2420. return path
  2421. end
  2422. return _ENV
  2423. end
  2424. --------------------------------------------------------------------------------
  2425. -- End of moduledebugger.url
  2426. --------------------------------------------------------------------------------
  2427. --------------------------------------------------------------------------------
  2428. -- Main content
  2429. --------------------------------------------------------------------------------
  2430. -------------------------------------------------------------------------------
  2431. -- Copyright (c) 2011-2012 Sierra Wireless and others.
  2432. -- All rights reserved. This program and the accompanying materials
  2433. -- are made available under the terms of the Eclipse Public License v1.0
  2434. -- which accompanies this distribution, and is available at
  2435. -- http://www.eclipse.org/legal/epl-v10.html
  2436. --
  2437. -- Contributors:
  2438. -- Sierra Wireless - initial API and implementation
  2439. -------------------------------------------------------------------------------
  2440. local DBGP_CLIENT_VERSION = "1.1.0"
  2441. local debug = require "debug"
  2442. -- To avoid cyclic dependency, internal state of the debugger that must be accessed
  2443. -- elsewhere (in commands most likely) will be stored in a fake module "debugger.core"
  2444. local core = { }
  2445. package.loaded["debugger.core"] = core
  2446. local util = require "debugger.util"
  2447. local platform = require "debugger.platform"
  2448. local dbgp = require "debugger.dbgp"
  2449. local commands = require "debugger.commands"
  2450. local context = require "debugger.context"
  2451. local url = require "debugger.url"
  2452. local log = util.log
  2453. -- TODO complete the stdlib access
  2454. local corunning, cocreate, cowrap, coyield, coresume, costatus = coroutine.running, coroutine.create, coroutine.wrap, coroutine.yield, coroutine.resume, coroutine.status
  2455. -- register the URI of the debugger, to not jump into with redefined function or coroutine bootstrap stuff
  2456. local debugger_uri = nil -- set in init function
  2457. local transportmodule_uri = nil -- set in init function
  2458. -- will contain the session object, and possibly a list of all sessions if a multi-threaded model is adopted
  2459. -- this is only used for async commands.
  2460. local active_session = nil
  2461. -- tracks all active coroutines and associate an id to them, the table from_id is the id=>coro mapping, the table from_coro is the reverse
  2462. core.active_coroutines = { n = 0, from_id = setmetatable({ }, { __mode = "v" }), from_coro = setmetatable({ }, { __mode = "k" }) }
  2463. -- "BEGIN VERSION DEPENDENT CODE"
  2464. local setbpenv -- set environment of a breakpoint (compiled function)
  2465. if _VERSION == "Lua 5.1" then
  2466. local setfenv = setfenv
  2467. setbpenv = setfenv
  2468. elseif _VERSION == "Lua 5.2" then
  2469. local setupvalue = debug.setupvalue
  2470. -- _ENV is the first upvalue
  2471. setbpenv = function(f, t) return setupvalue(f, 1, t) end
  2472. else error(_VERSION .. "is not supported.") end
  2473. -- "END VERSION DEPENDENT CODE"
  2474. -------------------------------------------------------------------------------
  2475. -- Output redirection handling
  2476. -------------------------------------------------------------------------------
  2477. -- Override standard output functions & constants to redirect data written to these files to IDE too.
  2478. -- This works only for output done in Lua, output written by C extensions is still go to system output file.
  2479. -- references to native values
  2480. io.base = { output = io.output, stdin = io.stdin, stdout = io.stdout, stderr = io.stderr }
  2481. function _print(...)
  2482. local buf = {...}
  2483. for i=1, select("#", ...) do
  2484. buf[i] = tostring(buf[i])
  2485. end
  2486. io.stdout:write(table.concat(buf, "\t") .. "\n")
  2487. end
  2488. local oldPrint = print
  2489. -- Actually change standard output file but still return the "fake" stdout
  2490. function io.output(output)
  2491. io.base.output(output)
  2492. return io.stdout
  2493. end
  2494. local dummy = function() end
  2495. -- metatable for redirecting output (not printed at all in actual output)
  2496. core.redirect_output = {
  2497. write = function(self, ...)
  2498. local buf = {...}
  2499. for i=1, select("#", ...) do buf[i] = tostring(buf[i]) end
  2500. buf = table.concat(buf):gsub("\n", "\r\n")
  2501. dbgp.send_xml(self.skt, { tag = "stream", attr = { type=self.mode }, util.b64(buf) } )
  2502. end,
  2503. flush = dummy,
  2504. close = dummy,
  2505. setvbuf = dummy,
  2506. seek = dummy
  2507. }
  2508. core.redirect_output.__index = core.redirect_output
  2509. -- metatable for cloning output (outputs to actual system and send to IDE)
  2510. core.copy_output = {
  2511. write = function(self, ...)
  2512. core.redirect_output.write(self, ...)
  2513. io.base[self.mode]:write(...)
  2514. end,
  2515. flush = function(self, ...) return self.out:flush(...) end,
  2516. close = function(self, ...) return self.out:close(...) end,
  2517. setvbuf = function(self, ...) return self.out:setvbuf(...) end,
  2518. seek = function(self, ...) return self.out:seek(...) end,
  2519. }
  2520. core.copy_output.__index = core.copy_output
  2521. -------------------------------------------------------------------------------
  2522. -- Breakpoint registry
  2523. -------------------------------------------------------------------------------
  2524. -- Registry of current stack levels of all running threads
  2525. local stack_levels = setmetatable( { }, { __mode = "k" } )
  2526. -- File/line mapping for breakpoints (BP). For a given file/line, a list of BP is associated (DBGp specification section 7.6.1
  2527. -- require that multiple BP at same place must be handled)
  2528. -- A BP is a table with all additional properties (type, condition, ...) the id is the string representation of the table.
  2529. core.breakpoints = {
  2530. -- functions to call to match hit conditions
  2531. hit_conditions = {
  2532. [">="] = function(value, target) return value >= target end,
  2533. ["=="] = function(value, target) return value == target end,
  2534. ["%"] = function(value, target) return (value % target) == 0 end,
  2535. }
  2536. }
  2537. -- tracks events such as step_into or step_over
  2538. core.events = { }
  2539. do
  2540. local file_mapping = { }
  2541. local id_mapping = { }
  2542. local waiting_sessions = { } -- sessions that wait for an event (over, into, out)
  2543. local step_into = nil -- session that registered a step_into event, if any
  2544. local sequence = 0 -- used to generate breakpoint IDs
  2545. --- Inserts a new breakpoint into registry
  2546. -- @param bp (table) breakpoint data
  2547. -- @param uri (string, optional) Absolute file URI, for line breakpoints
  2548. -- @param line (number, optional) Line where breakpoint stops, for line breakpoints
  2549. -- @return breakpoint identifier
  2550. function core.breakpoints.insert(bp)
  2551. local bpid = sequence
  2552. sequence = bpid + 1
  2553. bp.id = bpid
  2554. -- re-encode the URI to avoid any mismatch (with authority for example)
  2555. local uri = url.parse(bp.filename)
  2556. bp.filename = url.build{ scheme=uri.scheme, authority="", path=platform.normalize(uri.path)}
  2557. local filereg = file_mapping[bp.filename]
  2558. if not filereg then
  2559. filereg = { }
  2560. file_mapping[bp.filename] = filereg
  2561. end
  2562. local linereg = filereg[bp.lineno]
  2563. if not linereg then
  2564. linereg = {}
  2565. filereg[bp.lineno] = linereg
  2566. end
  2567. table.insert(linereg, bp)
  2568. id_mapping[bpid] = bp
  2569. return bpid
  2570. end
  2571. --- If breakpoint(s) exists for given file/line, uptates breakpoint counters
  2572. -- and returns whether a breakpoint has matched (boolean)
  2573. function core.breakpoints.at(file, line)
  2574. local bps = file_mapping[file] and file_mapping[file][line]
  2575. if not bps then return nil end
  2576. local do_break = false
  2577. for _, bp in pairs(bps) do
  2578. if bp.state == "enabled" then
  2579. local match = true
  2580. if bp.condition then
  2581. -- TODO: this is not the optimal solution because Context can be instantiated twice if the breakpoint matches
  2582. local cxt = context.Context:new(active_session.coro, 0)
  2583. setbpenv(bp.condition, cxt)
  2584. local success, result = pcall(bp.condition)
  2585. if not success then log("ERROR", "Condition evaluation failed for breakpoint at %s:%d: %s", file, line, result) end
  2586. -- debugger always stops if an error occurs
  2587. match = (not success) or result
  2588. end
  2589. if match then
  2590. bp.hit_count = bp.hit_count + 1
  2591. if core.breakpoints.hit_conditions[bp.hit_condition](bp.hit_count, bp.hit_value) then
  2592. if bp.temporary then
  2593. core.breakpoints.remove(bp.id)
  2594. end
  2595. do_break = true
  2596. -- there is no break to handle multiple breakpoints: all hit counts must be updated
  2597. end
  2598. end
  2599. end
  2600. end
  2601. return do_break
  2602. end
  2603. function core.breakpoints.get(id)
  2604. if id then return id_mapping[id]
  2605. else return id_mapping end
  2606. end
  2607. function core.breakpoints.remove(id)
  2608. local bp = id_mapping[id]
  2609. if bp then
  2610. id_mapping[id] = nil
  2611. local linereg = file_mapping[bp.filename][bp.lineno]
  2612. for i=1, #linereg do
  2613. if linereg[i] == bp then
  2614. table.remove(linereg, i)
  2615. break
  2616. end
  2617. end
  2618. -- cleanup file_mapping
  2619. if not next(linereg) then file_mapping[bp.filename][bp.lineno] = nil end
  2620. if not next(file_mapping[bp.filename]) then file_mapping[bp.filename] = nil end
  2621. return true
  2622. end
  2623. return false
  2624. end
  2625. --- Returns an XML data structure that describes given breakpoint
  2626. -- @param id (number) breakpoint ID
  2627. -- @return Table describing a <breakpooint> tag or nil followed by an error message
  2628. function core.breakpoints.get_xml(id)
  2629. local bp = id_mapping[id]
  2630. if not bp then return nil, "No such breakpoint: "..tostring(id) end
  2631. local response = { tag = "breakpoint", attr = { } }
  2632. for k,v in pairs(bp) do response.attr[k] = v end
  2633. if bp.expression then
  2634. response[1] = { tag = "expression", bp.expression }
  2635. end
  2636. -- internal use only
  2637. response.attr.expression = nil
  2638. response.attr.condition = nil
  2639. response.attr.temporary = nil -- TODO: the specification is not clear whether this should be provided, see other implementations
  2640. return response
  2641. end
  2642. --- Register an event to be triggered.
  2643. -- @param event event name to register (must be "over", "out" or "into")
  2644. function core.events.register(event)
  2645. local thread = active_session.coro[1]
  2646. log("DEBUG", "Registered %s event for %s (%d)", event, tostring(thread), stack_levels[thread])
  2647. if event == "into" then
  2648. step_into = true
  2649. else
  2650. waiting_sessions[thread] = { event, stack_levels[thread] }
  2651. end
  2652. end
  2653. --- Returns if an event (step into, over, out) is triggered.
  2654. -- Does *not* discard events (even if they match) as event must be discarded manually if a breakpoint match before anyway.
  2655. -- @return true if an event has matched, false otherwise
  2656. function core.events.does_match()
  2657. if step_into then return true end
  2658. local thread = active_session.coro[1]
  2659. local event = waiting_sessions[thread]
  2660. if event then
  2661. local event_type, target_level = unpack(event)
  2662. local current_level = stack_levels[thread]
  2663. if (event_type == "over" and current_level <= target_level) or -- step over
  2664. (event_type == "out" and current_level < target_level) then -- step out
  2665. log("DEBUG", "Event %s matched!", event_type)
  2666. return true
  2667. end
  2668. end
  2669. return false
  2670. end
  2671. --- Discards event for current thread (if any)
  2672. function core.events.discard()
  2673. waiting_sessions[active_session.coro[1]] = nil
  2674. step_into = nil
  2675. end
  2676. end
  2677. -------------------------------------------------------------------------------
  2678. -- Debugger main loop
  2679. -------------------------------------------------------------------------------
  2680. --- Send the XML response to the previous continuation command and clear the previous context
  2681. function core.previous_context_response(self, reason)
  2682. self.previous_context.status = self.state
  2683. self.previous_context.reason = reason or "ok"
  2684. dbgp.send_xml(self.skt, { tag = "response", attr = self.previous_context } )
  2685. self.previous_context = nil
  2686. end
  2687. local function cleanup()
  2688. coroutine.resume, coroutine.wrap = coresume, cowrap
  2689. for _, coro in pairs(core.active_coroutines.from_id) do
  2690. debug.sethook(coro)
  2691. end
  2692. -- to remove hook on the main coroutine, it must be the current one (otherwise, this is a no-op) and this function
  2693. -- have to be called adain later on the main thread to finish cleaup
  2694. debug.sethook()
  2695. print = oldPrint
  2696. core.active_coroutines.from_id, core.active_coroutines.from_coro = { }, { }
  2697. end
  2698. --- This function handles the debugger commands while the execution is paused. This does not use coroutines because there is no
  2699. -- way to get main coro in Lua 5.1 (only in 5.2)
  2700. local function debugger_loop(self, async_packet)
  2701. self.skt:settimeout(nil) -- set socket blocking
  2702. -- in async mode, the debugger does not wait for another command before continuing and does not modify previous_context
  2703. local async_mode = async_packet ~= nil
  2704. if self.previous_context and not async_mode then
  2705. self.state = "break"
  2706. core.previous_context_response(self)
  2707. end
  2708. self.stack = context.ContextManager(self.coro) -- will be used to mutualize context allocation for each loop
  2709. while true do
  2710. -- reads packet
  2711. local packet = async_packet or dbgp.read_packet(self.skt)
  2712. if not packet then
  2713. log("WARNING", "lost debugger connection")
  2714. cleanup()
  2715. break
  2716. end
  2717. async_packet = nil
  2718. log("DEBUG", packet)
  2719. local cmd, args, data = dbgp.cmd_parse(packet)
  2720. -- FIXME: command such as continuations sent in async mode could lead both engine and IDE in inconsistent state :
  2721. -- make a blacklist/whitelist of forbidden or allowed commands in async ?
  2722. -- invoke function
  2723. local func = commands[cmd]
  2724. if func then
  2725. local ok, cont = xpcall(function() return func(self, args, data) end, debug.traceback)
  2726. if not ok then -- internal exception
  2727. local code, msg, attr
  2728. if type(cont) == "table" and getmetatable(cont) == dbgp.DBGP_ERR_METATABLE then
  2729. code, msg, attr = cont.code, cont.message, cont.attr
  2730. else
  2731. code, msg, attr = 998, tostring(cont), { }
  2732. end
  2733. log("ERROR", "Command %s caused: (%d) %s", cmd, code, tostring(msg))
  2734. attr.command, attr.transaction_id = cmd, args.i
  2735. dbgp.send_xml(self.skt, { tag = "response", attr = attr, dbgp.make_error(code, msg) } )
  2736. elseif cont then
  2737. self.previous_context = { command = cmd, transaction_id = args.i }
  2738. break
  2739. elseif cont == nil and async_mode then
  2740. break
  2741. elseif cont == false then -- In case of commands that fully resumes debugger loop, the mode is sync
  2742. async_mode = false
  2743. end
  2744. else
  2745. log("Got unknown command: "..cmd)
  2746. dbgp.send_xml(self.skt, { tag = "response", attr = { command = cmd, transaction_id = args.i, }, dbgp.make_error(4) } )
  2747. end
  2748. end
  2749. self.stack = nil -- free allocated contexts
  2750. self.state = "running"
  2751. self.skt:settimeout(0) -- reset socket to async
  2752. end
  2753. -- Stack handling can be pretty complex sometimes, especially with LuaJIT (as tail-call optimization are
  2754. -- more aggressive as stock Lua). So all debugger stuff is done in another coroutine, which leave the program
  2755. -- stack in a clean state and allow faster and clearer stack operations (no need to remove all debugger calls
  2756. -- from stack for each operation).
  2757. -- However, this does not always work with stock Lua 5.1 as the main coroutine cannot be referenced
  2758. -- (coroutine.running() return nil). For this particular case, the debugger loop is started on the top of
  2759. -- program stack and every stack operation is relative the the hook level (see MainThread in util.lua).
  2760. local function line_hook(line)
  2761. local do_break, packet = nil, nil
  2762. local info = active_session.coro:getinfo(0, "S")
  2763. local uri = platform.get_uri(info.source)
  2764. if uri and uri ~= debugger_uri and uri ~= transportmodule_uri then -- the debugger does not break if the source is not known
  2765. do_break = core.breakpoints.at(uri, line) or core.events.does_match()
  2766. if do_break then
  2767. core.events.discard()
  2768. end
  2769. -- check for async commands
  2770. if not do_break then
  2771. packet = dbgp.read_packet(active_session.skt)
  2772. if packet then do_break = true end
  2773. end
  2774. end
  2775. if do_break then
  2776. local success, err = pcall(debugger_loop, active_session, packet)
  2777. if not success then log("ERROR", "Error while debug loop: "..err) end
  2778. end
  2779. end
  2780. local line_hook_coro = cocreate(function(line)
  2781. while true do
  2782. line_hook(line)
  2783. line = coyield()
  2784. end
  2785. end)
  2786. local function debugger_hook(event, line)
  2787. local thread = corunning() or "main"
  2788. if event == "call" then
  2789. stack_levels[thread] = stack_levels[thread] + 1
  2790. elseif event == "tail call" then
  2791. -- tail calls has no effects on stack handling: it is only used only for step commands but a such even does not
  2792. -- interfere with any of them
  2793. elseif event == "return" or event == "tail return" then
  2794. stack_levels[thread] = stack_levels[thread] - 1
  2795. else -- line event: check for breakpoint
  2796. active_session.coro = util.CurrentThread(corunning())
  2797. if active_session.coro[1] == "main" then
  2798. line_hook(line)
  2799. else
  2800. -- run the debugger loop in another thread on the other cases (simplifies stack handling)
  2801. assert(coresume(line_hook_coro, line))
  2802. end
  2803. active_session.coro = nil
  2804. end
  2805. end
  2806. if rawget(_G, "jit") then
  2807. debugger_hook = function(event, line)
  2808. local thread = corunning() or "main"
  2809. if event == "call" then
  2810. if debug.getinfo(2, "S").what == "C" then return end
  2811. stack_levels[thread] = stack_levels[thread] + 1
  2812. elseif event == "return" or event == "tail return" then
  2813. -- Return hooks are not called for tail calls in JIT (but unlike 5.2 there is no way to know whether a call is tail or not).
  2814. -- So the only reliable way to know stack depth is to walk it.
  2815. local depth = 2
  2816. -- TODO: find the fastest way to call getinfo ('what' parameter)
  2817. while debug.getinfo(depth, "f") do depth = depth + 1 end
  2818. stack_levels[thread] = depth - 2
  2819. elseif event == "line" then
  2820. active_session.coro = util.CurrentThread(corunning())
  2821. if active_session.coro[1] == "main" then
  2822. line_hook(line)
  2823. else
  2824. -- run the debugger loop in another thread on the other cases (simplifies stack handling)
  2825. assert(coresume(line_hook_coro, line))
  2826. end
  2827. active_session.coro = nil
  2828. end
  2829. end
  2830. end
  2831. local function init(host, port, idekey, transport, executionplatform, workingdirectory)
  2832. -- get connection data
  2833. local host = host or os.getenv "DBGP_IDEHOST" or "127.0.0.1"
  2834. local port = port or os.getenv "DBGP_IDEPORT" or "10000"
  2835. local idekey = idekey or os.getenv("DBGP_IDEKEY") or "luaidekey"
  2836. -- init plaform module
  2837. local executionplatform = executionplatform or os.getenv("DBGP_PLATFORM") or nil
  2838. local workingdirectory = workingdirectory or os.getenv("DBGP_WORKINGDIR") or nil
  2839. platform.init(executionplatform,workingdirectory)
  2840. -- get transport layer
  2841. local transportpath = transport or os.getenv("DBGP_TRANSPORT") or "debugger.transport.luasocket"
  2842. local transport = require(transportpath)
  2843. -- install base64 functions into util
  2844. util.b64, util.rawb64, util.unb64 = transport.b64, transport.rawb64, transport.unb64
  2845. local skt = assert(transport.create())
  2846. skt:settimeout(nil)
  2847. -- try to connect several times: if IDE launches both process and server at same time, first connect attempts may fail
  2848. local ok, err
  2849. print(string.format("Debugger v%s", DBGP_CLIENT_VERSION))
  2850. print(string.format("Debugger: Trying to connect to %s:%s ... ", host, port))
  2851. ok, err = skt:connect(host, port)
  2852. --for i=1, 4 do
  2853. if ok then
  2854. print("Debugger: Connection succeed.")
  2855. --break
  2856. --else
  2857. -- wait
  2858. --transport.sleep(0.5)
  2859. -- then retry.
  2860. --print(string.format("Debugger: Retrying to connect to %s:%s ... ", host, port))
  2861. --ok, err = skt:connect(host, port)
  2862. end
  2863. --end
  2864. --if err then error(string.format("Cannot connect to %s:%d : %s", host, port, err)) end
  2865. if err then
  2866. print(string.format("Cannot connect to %s:%d : %s", host, port, err));
  2867. return;
  2868. end
  2869. print = function(...)
  2870. oldPrint(...)
  2871. _print(...)
  2872. end
  2873. -- get the debugger and transport layer URI
  2874. debugger_uri = platform.get_uri(debug.getinfo(1).source)
  2875. transportmodule_uri = platform.get_uri(debug.getinfo(transport.create).source)
  2876. -- get the root script path (the highest possible stack index)
  2877. local source
  2878. for i=2, math.huge do
  2879. local info = debug.getinfo(i)
  2880. if not info then break end
  2881. source = platform.get_uri(info.source) or source
  2882. end
  2883. if not source then source = "unknown:/" end -- when loaded before actual script (with a command line switch)
  2884. -- generate some kind of thread identifier
  2885. local thread = corunning() or "main"
  2886. stack_levels[thread] = 1 -- the return event will set the counter to 0
  2887. local sessionid = tostring(os.time()) .. "_" .. tostring(thread)
  2888. dbgp.send_xml(skt, { tag = "init", attr = {
  2889. appid = "Lua DBGp",
  2890. idekey = idekey,
  2891. session = sessionid,
  2892. thread = tostring(thread),
  2893. parent = "",
  2894. language = "Lua",
  2895. protocol_version = "1.0",
  2896. fileuri = source
  2897. } })
  2898. --FIXME util.CurrentThread(corunning) => util.CurrentThread(corunning()) WHAT DOES IT FIXES ??
  2899. local sess = { skt = skt, state = "starting", id = sessionid, coro = util.CurrentThread(corunning) }
  2900. active_session = sess
  2901. debugger_loop(sess)
  2902. -- set debug hooks
  2903. debug.sethook(debugger_hook, "rlc")
  2904. -- install coroutine collecting functions.
  2905. -- TODO: maintain a list of *all* coroutines can be overkill (for example, the ones created by copcall), make a extension point to
  2906. -- customize debugged coroutines
  2907. -- coroutines are referenced during their first resume (so we are sure that they always have a stack frame)
  2908. local function resume_handler(coro, ...)
  2909. if costatus(coro) == "dead" then
  2910. local coro_id = core.active_coroutines.from_coro[coro]
  2911. core.active_coroutines.from_id[coro_id] = nil
  2912. core.active_coroutines.from_coro[coro] = nil
  2913. stack_levels[coro] = nil
  2914. end
  2915. return ...
  2916. end
  2917. function coroutine.resume(coro, ...)
  2918. if not stack_levels[coro] then
  2919. -- first time referenced
  2920. stack_levels[coro] = 0
  2921. core.active_coroutines.n = core.active_coroutines.n + 1
  2922. core.active_coroutines.from_id[core.active_coroutines.n] = coro
  2923. core.active_coroutines.from_coro[coro] = core.active_coroutines.n
  2924. debug.sethook(coro, debugger_hook, "rlc")
  2925. end
  2926. return resume_handler(coro, coresume(coro, ...))
  2927. end
  2928. -- coroutine.wrap uses directly C API for coroutines and does not trigger our overridden coroutine.resume
  2929. -- so this is an implementation of wrap in pure Lua
  2930. local function wrap_handler(status, ...)
  2931. if not status then error((...)) end
  2932. return ...
  2933. end
  2934. function coroutine.wrap(f)
  2935. local coro = coroutine.create(f)
  2936. return function(...)
  2937. return wrap_handler(coroutine.resume(coro, ...))
  2938. end
  2939. end
  2940. return sess
  2941. end
  2942. return init