GDB (xrefs)
Loading...
Searching...
No Matches
bt.py
Go to the documentation of this file.
1# Copyright 2022-2023 Free Software Foundation, Inc.
2
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 3 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16import gdb
17import os
18
19# This is deprecated in 3.9, but required in older versions.
20from typing import Optional
21
22from .frames import dap_frame_generator
23from .modules import module_id
24from .scopes import symbol_value
25from .server import request, capability
26from .sources import make_source
27from .startup import in_gdb_thread
28from .state import set_thread
29from .typecheck import type_check
30from .varref import apply_format
31
32
33# Helper function to compute parameter information for a stack frame.
34@in_gdb_thread
35def _compute_parameters(frame, stack_format):
36 arg_iter = frame.frame_args()
37 if arg_iter is None:
38 return ""
39 result = []
40 for arg in arg_iter:
41 desc = []
42 name, val = symbol_value(arg, frame)
43 # We don't try to use any particular language's syntax for the
44 # output here.
45 if stack_format["parameterTypes"]:
46 desc.append("[" + str(val.type) + "]")
47 if stack_format["parameterNames"]:
48 desc.append(name)
49 # If both the name and the value are requested, insert an
50 # '=' for clarity.
51 if stack_format["parameterValues"]:
52 desc.append("=")
53 if stack_format["parameterValues"]:
54 desc.append(val.format_string(summary=True))
55 result.append(" ".join(desc))
56 return ", ".join(result)
57
58
59# Helper function to compute a stack trace.
60@in_gdb_thread
61def _backtrace(thread_id, levels, startFrame, stack_format):
62 with apply_format(stack_format):
63 set_thread(thread_id)
64 frames = []
65 frame_iter = dap_frame_generator(startFrame, levels, stack_format["includeAll"])
66 for frame_id, current_frame in frame_iter:
67 pc = current_frame.address()
68 # The stack frame format affects the name, so we build it up
69 # piecemeal and assign it at the end.
70 name = current_frame.function()
71 # The meaning of StackFrameFormat.parameters was clarified
72 # in https://github.com/microsoft/debug-adapter-protocol/issues/411.
73 if stack_format["parameters"] and (
74 stack_format["parameterTypes"]
75 or stack_format["parameterNames"]
76 or stack_format["parameterValues"]
77 ):
78 name += "(" + _compute_parameters(current_frame, stack_format) + ")"
79 newframe = {
80 "id": frame_id,
81 # This must always be supplied, but we will set it
82 # correctly later if that is possible.
83 "line": 0,
84 # GDB doesn't support columns.
85 "column": 0,
86 "instructionPointerReference": hex(pc),
87 }
88 line = current_frame.line()
89 if line is not None:
90 newframe["line"] = line
91 if stack_format["line"]:
92 name += ", line " + str(line)
93 objfile = gdb.current_progspace().objfile_for_address(pc)
94 if objfile is not None:
95 newframe["moduleId"] = module_id(objfile)
96 if stack_format["module"]:
97 name += ", module " + objfile.username
98 filename = current_frame.filename()
99 if filename is not None:
100 newframe["source"] = make_source(filename, os.path.basename(filename))
101 newframe["name"] = name
102 frames.append(newframe)
103 # Note that we do not calculate totalFrames here. Its absence
104 # tells the client that it may simply ask for frames until a
105 # response yields fewer frames than requested.
106 return {
107 "stackFrames": frames,
108 }
109
110
111# A helper function that checks the types of the elements of a
112# StackFrameFormat, and converts this to a dict where all the members
113# are set. This simplifies the implementation code a bit.
114@type_check
116 *,
117 # Note that StackFrameFormat extends ValueFormat, which is why
118 # "hex" appears here.
119 hex: Optional[bool] = False,
120 parameters: Optional[bool] = False,
121 parameterTypes: Optional[bool] = False,
122 parameterNames: Optional[bool] = False,
123 parameterValues: Optional[bool] = False,
124 line: Optional[bool] = False,
125 module: Optional[bool] = False,
126 includeAll: Optional[bool] = False,
127 **rest
128):
129 return {
130 "hex": hex,
131 "parameters": parameters,
132 "parameterTypes": parameterTypes,
133 "parameterNames": parameterNames,
134 "parameterValues": parameterValues,
135 "line": line,
136 "module": module,
137 "includeAll": includeAll,
138 }
139
140
141@request("stackTrace")
142@capability("supportsDelayedStackTraceLoading")
144 *, levels: int = 0, startFrame: int = 0, threadId: int, format=None, **extra
145):
146 # It's simpler if the format is always set.
147 if format is None:
148 format = {}
149 format = check_stack_frame(**format)
150 return _backtrace(threadId, levels, startFrame, format)
stacktrace(*int levels=0, int startFrame=0, int threadId, format=None, **extra)
Definition bt.py:145
_backtrace(thread_id, levels, startFrame, stack_format)
Definition bt.py:61
check_stack_frame(*Optional[bool] hex=False, Optional[bool] parameters=False, Optional[bool] parameterTypes=False, Optional[bool] parameterNames=False, Optional[bool] parameterValues=False, Optional[bool] line=False, Optional[bool] module=False, Optional[bool] includeAll=False, **rest)
Definition bt.py:128
_compute_parameters(frame, stack_format)
Definition bt.py:35
current_progspace()
Definition __init__.py:211