Skip to content

Commit

Permalink
feat(dap): added printing symbolicated crash call stack (#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
wojciech-kulik authored Feb 3, 2025
1 parent 08f1067 commit b6a1e01
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 0 deletions.
20 changes: 20 additions & 0 deletions doc/xcodebuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Xcresult File Parser ························ |xcodebuil
Code Coverage ······························ |xcodebuild.code_coverage.coverage|
Code Coverage Report ························· |xcodebuild.code_coverage.report|
DAP Integration ·································· |xcodebuild.integrations.dap|
DAP Symbolicate ······················ |xcodebuild.integrations.dap-symbolicate|
Remote Debugger Integration ·········· |xcodebuild.integrations.remote_debugger|
LSP Integration ·································· |xcodebuild.integrations.lsp|
nvim-tree Integration ······················ |xcodebuild.integrations.nvim-tree|
Expand Down Expand Up @@ -3763,6 +3764,25 @@ M.setup({codelldbPath}, {loadBreakpoints})
{loadBreakpoints} (boolean|nil) default: true


==============================================================================
DAP Symbolicate *xcodebuild.integrations.dap-symbolicate*

This module provides a DAP integration for symbolication of crash call stacks.

*xcodebuild.integrations.dap-symbolicate.process_logs*
M.process_logs({output}, {on_symbolicate})
Collects the crash call stack from the console output.

Parameters: ~
{output} (string[]) # the console output
{on_symbolicate} (fun(symbolicatedCallStack:string[])) # callback with the symbolicated call stack


*xcodebuild.integrations.dap-symbolicate.dap_started*
M.dap_started()
Use to notify the module that the debugger has started.


==============================================================================
Remote Debugger Integration *xcodebuild.integrations.remote_debugger*

Expand Down
125 changes: 125 additions & 0 deletions lua/xcodebuild/integrations/dap-symbolicate.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---@mod xcodebuild.integrations.dap-symbolicate DAP Symbolicate
---@brief [[
---This module provides a DAP integration for symbolication of crash call stacks.
---@brief ]]

local M = {}

local PLUGIN_ID = "xcodebuild-dap-symbolicate-"

local foundException = false
local crashCallStack = {}

---Escapes magic characters from Lua patterns.
---@param s string # the string to escape
local function escape_magic(s)
return (s:gsub("[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%1"))
end

---Symbolicates the given address using the debugger.
---@param address string # the address to symbolicate
---@param callback fun(symbolicated: string) # callback with the symbolicated address
local function repl_symbolicate(address, callback)
local dap = require("dap")

dap.listeners.after.event_output[PLUGIN_ID .. address] = function(_, body)
if body.category == "console" then
local symbolicated = body.output:match("Summary: [^`]*`?(.*)")
if symbolicated then
dap.listeners.after.event_output[PLUGIN_ID .. address] = nil
callback(symbolicated)
end
end
end

dap.session():request("evaluate", {
expression = "image lookup -a " .. address,
context = "repl",
})
end

---Symbolicates the crash call stack.
---@param callStack string[]
---@param callback fun(symbolicatedCallStack: string[]) # symbolicated call stack
local function symbolicate(callStack, callback)
local result = {}

local co = coroutine.create(function(co)
for index, line in ipairs(callStack) do
result[index] = line:gsub("\n", "")

local address, frame = line:match("(0x%x+)%s*(.*)")
if not address then
goto continue
end

-- symbolicate the address
repl_symbolicate(address, function(symbolicated)
if symbolicated then
result[index] = line:gsub(escape_magic(frame), symbolicated):gsub("\n", "")
end

-- if this is the last line, call the callback
if index == #callStack then
vim.schedule(function()
local output = {
"",
"==============================================",
"",
"Symbolicated crash call stack:",
"",
}
for _, l in ipairs(result) do
table.insert(output, l)
end

callback(output)
end)
end

-- continue to the next line
coroutine.resume(co, co)
end)

-- wait for the symbolication to finish
coroutine.yield()

::continue::
end
end)

coroutine.resume(co, co)
end

---Collects the crash call stack from the console output.
---@param output string[] # the console output
---@param on_symbolicate fun(symbolicatedCallStack: string[]) # callback with the symbolicated call stack
function M.process_logs(output, on_symbolicate)
for _, line in ipairs(output) do
if foundException then
if line == ")" then
foundException = false

-- defer to allow DAP print the original output
vim.defer_fn(function()
symbolicate(crashCallStack, function(symbolicated)
on_symbolicate(symbolicated)
end)
end, 100)

break
else
table.insert(crashCallStack, line)
end
else
foundException = line:find("__exceptionPreprocess") ~= nil
end
end
end

---Use to notify the module that the debugger has started.
function M.dap_started()
foundException = false
end

return M
9 changes: 9 additions & 0 deletions lua/xcodebuild/integrations/dap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ local projectConfig = require("xcodebuild.project.config")
local device = require("xcodebuild.platform.device")
local actions = require("xcodebuild.actions")
local remoteDebugger = require("xcodebuild.integrations.remote_debugger")
local dapSymbolicate = require("xcodebuild.integrations.dap-symbolicate")

local M = {}

Expand All @@ -74,6 +75,7 @@ local function start_dap()
return
end

dapSymbolicate.dap_started()
dap.run(dap.configurations.swift[1])
end

Expand Down Expand Up @@ -412,6 +414,13 @@ function M.update_console(output, append)
return
end

dapSymbolicate.process_logs(output, function(symbolicated)
vim.bo[bufnr].modifiable = true
vim.api.nvim_buf_set_lines(bufnr, -1, -1, false, symbolicated)
vim.bo[bufnr].modified = false
vim.bo[bufnr].modifiable = false
end)

vim.bo[bufnr].modifiable = true

local autoscroll = false
Expand Down
1 change: 1 addition & 0 deletions scripts/help-update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ lemmy-help \
./lua/xcodebuild/code_coverage/coverage.lua \
./lua/xcodebuild/code_coverage/report.lua \
./lua/xcodebuild/integrations/dap.lua \
./lua/xcodebuild/integrations/dap-symbolicate.lua \
./lua/xcodebuild/integrations/remote_debugger.lua \
./lua/xcodebuild/integrations/lsp.lua \
./lua/xcodebuild/integrations/nvim-tree.lua \
Expand Down

0 comments on commit b6a1e01

Please sign in to comment.